Skip to content

Commit

Permalink
working as expected
Browse files Browse the repository at this point in the history
  • Loading branch information
roncodes committed Jun 18, 2024
1 parent b4d73a2 commit 778d1a3
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 19 deletions.
7 changes: 5 additions & 2 deletions lib/FleetbaseClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.createFleetbaseClient = void 0;
const axios_1 = __importDefault(require("axios"));
const getConfigValue_1 = __importDefault(require("./getConfigValue"));
const createFleetbaseClient = (config) => {
const fleetbaseHost = (0, getConfigValue_1.default)('FLEETBASE_HOST', config);
const fleetbaseApiKey = (0, getConfigValue_1.default)('FLEETBASE_API_KEY', config);
const instance = axios_1.default.create({
baseURL: `${config.fleetbaseHost}/~registry/v1/`,
baseURL: `${fleetbaseHost}/~registry/v1/`,
headers: {
Authorization: `Bearer ${config.fleetbaseApiKey}`,
Authorization: `Bearer ${fleetbaseApiKey}`,
'Content-Type': 'application/json',
},
});
Expand Down
3 changes: 3 additions & 0 deletions lib/getConfigValue.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { FleetbaseRegistryAuthConfig } from './config';
declare const _default: (key: string, config: FleetbaseRegistryAuthConfig) => string;
export default _default;
13 changes: 13 additions & 0 deletions lib/getConfigValue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function toCamelCase(str) {
return str
.split(/[-_ ]+/)
.map((word, index) => (index === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()))
.join('');
}
exports.default = (key, config) => {
const envValue = process.env[key];
const configKey = toCamelCase(key);
return envValue || config[configKey];
};
4 changes: 2 additions & 2 deletions lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ export default class FleetbaseAuthPlugin implements IPluginAuth<Config> {
constructor(config: Config, options: any);
authenticate(identity: string, password: string, callback: Callback): Promise<void>;
adduser(identity: string, password: string, callback: Callback): Promise<void>;
allow_access(user: RemoteUser, pkg: (Config & PackageAccess) | (AllowAccess & PackageAccess), cb: AuthAccessCallback): void;
allow_publish(user: RemoteUser, pkg: PackageAccess, cb: Callback): void;
allow_access(user: RemoteUser, pkg: (Config & PackageAccess) | (AllowAccess & PackageAccess), callback: AuthAccessCallback): Promise<void>;
allow_publish(user: RemoteUser, pkg: PackageAccess, callback: Callback): Promise<void>;
}
55 changes: 49 additions & 6 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const commons_api_1 = require("@verdaccio/commons-api");
const fleetbaseClient_1 = require("./fleetbaseClient");
const getConfigValue_1 = __importDefault(require("./getConfigValue"));
class FleetbaseAuthPlugin {
config;
fleetbaseClient;
logger;
constructor(config, options) {
this.config = Object.assign(config, config.auth['@fleetbase/verdaccio-fleetbase-auth']);
this.logger = options.logger;
this.logger.debug({
config: JSON.stringify({
fleetbaseHost: (0, getConfigValue_1.default)('FLEETBASE_HOST', this.config),
fleetbaseApiKey: (0, getConfigValue_1.default)('FLEETBASE_API_KEY', this.config),
}, null, 4),
}, 'FLEETBASE CLIENT ENV/CONFIG VARS: @{config}');
this.fleetbaseClient = (0, fleetbaseClient_1.createFleetbaseClient)(this.config);
}
async authenticate(identity, password, callback) {
this.logger.debug({ identity }, 'Auth::authenticate() - Authenticating user with identity: @{identity}');
try {
const response = await this.fleetbaseClient.post('auth/authenticate', { identity, password });
this.logger.debug({ response: response.data }, 'Auth::authenticate() - Response from Fleetbase: @{response}');
const { groups } = response.data;
callback(null, groups);
this.logger.debug({ groups: JSON.stringify(groups) }, 'Auth::authenticate() -Groups: @{groups}');
callback(null, groups ?? []);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Authentication failed for creating developer account';
Expand All @@ -29,7 +41,7 @@ class FleetbaseAuthPlugin {
this.logger.debug({ identity, password }, 'Auth::addUser() - Creating registry user with identity: @{identity} and password: @{password}');
try {
const response = await this.fleetbaseClient.post('auth/add-user', { identity, password });
this.logger.debug({ response }, 'Auth::addUser() - Respone from Fleetbase: @{response}');
this.logger.debug({ response: response.data }, 'Auth::addUser() - Response from Fleetbase: @{response}');
const { token } = response.data;
this.logger.debug({ token }, 'Auth::addUser() - Token Generated: @{token}');
callback(null, true);
Expand All @@ -39,11 +51,42 @@ class FleetbaseAuthPlugin {
callback(error);
}
}
allow_access(user, pkg, cb) {
// Example implementation, modify based on your access logic
async allow_access(user, pkg, callback) {
// Allow access should check with Fleetbase API and see that registry user has access to the extension
this.logger.debug({ user }, 'Auth::allow_access() - User: @{user}');
this.logger.debug({ pkg }, 'Auth::allow_access() - Package: @{pkg}');
try {
const response = await this.fleetbaseClient.post('auth/check-access', { identity: user.name });
this.logger.debug({ response }, 'Auth::allow_access() - Response from Fleetbase: @{response}');
const { allowed } = response.data;
this.logger.debug({ allowed }, 'Auth::allow_access() - Allowed: @{allowed}');
callback(null, allowed);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Access denied';
const err = (0, commons_api_1.getForbidden)(errorMessage);
this.logger.debug({ error: errorMessage }, 'Auth::allow_access() - Access not granted: @{error}');
callback(err, false);
}
}
allow_publish(user, pkg, cb) {
// Example implementation, adjust according to your publish logic
async allow_publish(user, pkg, callback) {
// Allow publish should check with Fleetbase API for the extension and check the status for approved
// After publish registry should update the extension as published
this.logger.debug({ user }, 'Auth::allow_publish() - User: @{user}');
this.logger.debug({ pkg }, 'Auth::allow_publish() - Package: @{pkg}');
try {
const response = await this.fleetbaseClient.post('auth/check-publish', { identity: user.name, package: pkg.name });
this.logger.debug({ response }, 'Auth::allow_publish() - Response from Fleetbase: @{response}');
const { allowed } = response.data;
this.logger.debug({ allowed }, 'Auth::allow_publish() - Allowed: @{allowed}');
callback(null, allowed);
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Publish forbidden';
const err = (0, commons_api_1.getForbidden)(errorMessage);
this.logger.debug({ error: errorMessage }, 'Auth::allow_publish() - Publish forbidden: @{error}');
callback(err, false);
}
}
}
exports.default = FleetbaseAuthPlugin;
7 changes: 5 additions & 2 deletions src/FleetbaseClient.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import axios, { AxiosInstance } from 'axios';
import { FleetbaseRegistryAuthConfig } from './config';
import getConfigValue from './getConfigValue';

export interface IFleetbaseClient extends AxiosInstance {}

export const createFleetbaseClient = (config: FleetbaseRegistryAuthConfig): IFleetbaseClient => {
const fleetbaseHost = getConfigValue('FLEETBASE_HOST', config);
const fleetbaseApiKey = getConfigValue('FLEETBASE_API_KEY', config);
const instance = axios.create({
baseURL: `${config.fleetbaseHost}/~registry/v1/`,
baseURL: `${fleetbaseHost}/~registry/v1/`,
headers: {
Authorization: `Bearer ${config.fleetbaseApiKey}`,
Authorization: `Bearer ${fleetbaseApiKey}`,
'Content-Type': 'application/json',
},
});
Expand Down
14 changes: 14 additions & 0 deletions src/getConfigValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { FleetbaseRegistryAuthConfig } from './config';

function toCamelCase(str: string): string {
return str
.split(/[-_ ]+/)
.map((word, index) => (index === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()))
.join('');
}

export default (key: string, config: FleetbaseRegistryAuthConfig): string => {
const envValue = process.env[key];
const configKey = toCamelCase(key);
return envValue || config[configKey];
};
61 changes: 54 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { IPluginAuth, AuthPluginPackage, Callback, Config, RemoteUser, AllowAccess, AuthAccessCallback, PackageAccess, Logger } from '@verdaccio/types';
import { getConflict } from '@verdaccio/commons-api';
import { getConflict, getForbidden } from '@verdaccio/commons-api';
import { createFleetbaseClient, IFleetbaseClient } from './fleetbaseClient';
import { FleetbaseRegistryAuthConfig } from './config';
import { Application } from 'express';
import getConfigValue from './getConfigValue';

export { FleetbaseRegistryAuthConfig };
export default class FleetbaseAuthPlugin implements IPluginAuth<Config> {
Expand All @@ -13,6 +14,19 @@ export default class FleetbaseAuthPlugin implements IPluginAuth<Config> {
public constructor(config: Config, options: any) {
this.config = Object.assign(config, config.auth['@fleetbase/verdaccio-fleetbase-auth']);
this.logger = options.logger;
this.logger.debug(
{
config: JSON.stringify(
{
fleetbaseHost: getConfigValue('FLEETBASE_HOST', this.config),
fleetbaseApiKey: getConfigValue('FLEETBASE_API_KEY', this.config),
},
null,
4
),
},
'FLEETBASE CLIENT ENV/CONFIG VARS: @{config}'
);
this.fleetbaseClient = createFleetbaseClient(this.config);
}

Expand All @@ -21,9 +35,11 @@ export default class FleetbaseAuthPlugin implements IPluginAuth<Config> {

try {
const response = await this.fleetbaseClient.post('auth/authenticate', { identity, password });
this.logger.debug({ response: response.data }, 'Auth::authenticate() - Response from Fleetbase: @{response}');
const { groups } = response.data;
this.logger.debug({ groups: JSON.stringify(groups) }, 'Auth::authenticate() -Groups: @{groups}');

callback(null, groups);
callback(null, groups ?? []);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Authentication failed for creating developer account';
const conflict = getConflict(errorMessage);
Expand All @@ -36,7 +52,7 @@ export default class FleetbaseAuthPlugin implements IPluginAuth<Config> {
this.logger.debug({ identity, password }, 'Auth::addUser() - Creating registry user with identity: @{identity} and password: @{password}');
try {
const response = await this.fleetbaseClient.post('auth/add-user', { identity, password });
this.logger.debug({ response }, 'Auth::addUser() - Respone from Fleetbase: @{response}');
this.logger.debug({ response: response.data }, 'Auth::addUser() - Response from Fleetbase: @{response}');
const { token } = response.data;
this.logger.debug({ token }, 'Auth::addUser() - Token Generated: @{token}');

Expand All @@ -47,11 +63,42 @@ export default class FleetbaseAuthPlugin implements IPluginAuth<Config> {
}
}

public allow_access(user: RemoteUser, pkg: (Config & PackageAccess) | (AllowAccess & PackageAccess), cb: AuthAccessCallback): void {
// Example implementation, modify based on your access logic
public async allow_access(user: RemoteUser, pkg: (Config & PackageAccess) | (AllowAccess & PackageAccess), callback: AuthAccessCallback): Promise<void> {
// Allow access should check with Fleetbase API and see that registry user has access to the extension
this.logger.debug({ user }, 'Auth::allow_access() - User: @{user}');
this.logger.debug({ pkg }, 'Auth::allow_access() - Package: @{pkg}');
try {
const response = await this.fleetbaseClient.post('auth/check-access', { identity: user.name });
this.logger.debug({ response }, 'Auth::allow_access() - Response from Fleetbase: @{response}');
const { allowed } = response.data;
this.logger.debug({ allowed }, 'Auth::allow_access() - Allowed: @{allowed}');

callback(null, allowed);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Access denied';
const err = getForbidden(errorMessage);
this.logger.debug({ error: errorMessage }, 'Auth::allow_access() - Access not granted: @{error}');
callback(err, false);
}
}

public allow_publish(user: RemoteUser, pkg: PackageAccess, cb: Callback): void {
// Example implementation, adjust according to your publish logic
public async allow_publish(user: RemoteUser, pkg: PackageAccess, callback: Callback): Promise<void> {
// Allow publish should check with Fleetbase API for the extension and check the status for approved
// After publish registry should update the extension as published
this.logger.debug({ user }, 'Auth::allow_publish() - User: @{user}');
this.logger.debug({ pkg }, 'Auth::allow_publish() - Package: @{pkg}');
try {
const response = await this.fleetbaseClient.post('auth/check-publish', { identity: user.name, package: pkg.name });
this.logger.debug({ response }, 'Auth::allow_publish() - Response from Fleetbase: @{response}');
const { allowed } = response.data;
this.logger.debug({ allowed }, 'Auth::allow_publish() - Allowed: @{allowed}');

callback(null, allowed);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Publish forbidden';
const err = getForbidden(errorMessage);
this.logger.debug({ error: errorMessage }, 'Auth::allow_publish() - Publish forbidden: @{error}');
callback(err, false);
}
}
}

0 comments on commit 778d1a3

Please sign in to comment.