@fraym/auth 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,139 @@
1
+ # auth-nodejs
2
+
3
+ Client implementation in javascript for the [auth service](https://github.com/fraym/auth).
4
+
5
+ ## Installation
6
+
7
+ ```shell
8
+ npm i @fraym/auth
9
+ ```
10
+
11
+ ## GraphQL
12
+
13
+ You can access the graphQL api at `http://auth:3000/management/graphql`.
14
+ There is a sandbox available at `http://auth:3000/management/graphql/sandbox`.
15
+
16
+ You need to add the `Tenant-Id` header in order to use the graphQL Endpoint and the sandbox.
17
+
18
+ ## CLI command
19
+
20
+ Use the `auth` cli command to automatically apply your permissions to the auth service.
21
+
22
+ You can specify the address (and port) of the auth service instance you use in the `AUTH_SERVER_ADDRESS` env variable (default: `127.0.0.1:9000`).
23
+
24
+ The needed schema for auth is a simple enum containing all your permissions. Example:
25
+
26
+ ```graphql
27
+ enum Permission {
28
+ USER_READ
29
+ USER_WRITE
30
+ }
31
+ ```
32
+
33
+ ### Config
34
+
35
+ Use a `.env` file or env variables to configure cte clients and the command:
36
+
37
+ ```env
38
+ AUTH_SERVER_ADDRESS=127.0.0.1:9000
39
+ ```
40
+
41
+ ## Usage
42
+
43
+ ### Create the client
44
+
45
+ management client:
46
+
47
+ ```typescript
48
+ const managementClient = await newManagementClient();
49
+ ```
50
+
51
+ ## Get all scopes (permissions)
52
+
53
+ The `clientId` paramenter is optional. If none is given the default client will be used.
54
+
55
+ ```typescript
56
+ const scopes = await managementClient.getScopes();
57
+ ```
58
+
59
+ ## Create a scope (permission)
60
+
61
+ The `clientId` paramenter is optional. If none is given the default client will be used.
62
+
63
+ ```typescript
64
+ await managementClient.createScope("PERMISSION_NAME");
65
+ ```
66
+
67
+ ## Delete a scope (permission)
68
+
69
+ The `clientId` paramenter is optional. If none is given the default client will be used.
70
+
71
+ ```typescript
72
+ await managementClient.deleteScope("PERMISSION_NAME");
73
+ ```
74
+
75
+ ## Get all roles
76
+
77
+ ```typescript
78
+ const roles = await managementClient.getRoles("TENANT_ID");
79
+ ```
80
+
81
+ ## Upsert a role
82
+
83
+ ```typescript
84
+ await managementClient.upsertRole("TENANT_ID", "ROLE_ID", [
85
+ {
86
+ scopeName: "PERMISSION_NAME",
87
+ // optional: clientId: If none is given the default client will be used
88
+ },
89
+ ]);
90
+ ```
91
+
92
+ ## Delete a role
93
+
94
+ ```typescript
95
+ await managementClient.deleteRole("TENANT_ID", "ROLE_ID");
96
+ ```
97
+
98
+ ### Gracefully close the clients
99
+
100
+ You won't lose any data if you don't. Use it for your peace of mind.
101
+
102
+ ```typescript
103
+ client.close();
104
+ ```
105
+
106
+ ## Development
107
+
108
+ You'll need the following apps for a smooth development experience:
109
+
110
+ - minikube
111
+ - lens
112
+ - okteto
113
+ - helm
114
+
115
+ ### Running the dev environment
116
+
117
+ - Start minikube if not already done:
118
+
119
+ ```shell
120
+ minikube start
121
+ ```
122
+
123
+ - add mongodb and minio to your lokal kubernetes
124
+ - use Makefiles in `./.dev/*`
125
+ - copy `.env.build` to `.env.build.local`
126
+ - add your personal access token (needs read access for private fraym org repositories)
127
+ - deploy the app to your cluster
128
+
129
+ ```
130
+ make init
131
+ ```
132
+
133
+ - start okteto
134
+
135
+ ```
136
+ make dev
137
+ ```
138
+
139
+ - connect your IDE to that okteto instance
@@ -0,0 +1,2 @@
1
+ #! /usr/bin/env node
2
+ export {};
@@ -0,0 +1,76 @@
1
+ #! /usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const yargs_1 = __importDefault(require("yargs/yargs"));
8
+ const helpers_1 = require("yargs/helpers");
9
+ const dotenv_1 = require("dotenv");
10
+ const graphql_file_loader_1 = require("@graphql-tools/graphql-file-loader");
11
+ const load_1 = require("@graphql-tools/load");
12
+ const graphql_1 = require("graphql");
13
+ const client_1 = require("../management/client");
14
+ const run = async () => {
15
+ (0, dotenv_1.config)();
16
+ const argv = await (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
17
+ .config({
18
+ schemaGlob: "./src/**/*.graphql",
19
+ serverAddress: "127.0.0.1:9000",
20
+ })
21
+ .pkgConf("auth").argv;
22
+ let schemaGlob = argv.schemaGlob;
23
+ let serverAddress = argv.serverAddress;
24
+ if (process.env.AUTH_SCHEMA_GLOB) {
25
+ schemaGlob = process.env.AUTH_SCHEMA_GLOB;
26
+ }
27
+ if (process.env.AUTH_SERVER_ADDRESS) {
28
+ serverAddress = process.env.AUTH_SERVER_ADDRESS;
29
+ }
30
+ const schema = await (0, load_1.loadSchema)(`${schemaGlob}`, {
31
+ loaders: [new graphql_file_loader_1.GraphQLFileLoader()],
32
+ });
33
+ const permissions = getSchemaPermissions(schema);
34
+ await migratePermissions(permissions, serverAddress);
35
+ };
36
+ const getSchemaPermissions = (schema) => {
37
+ const permissions = [];
38
+ schema.toConfig().types.forEach(t => {
39
+ var _a, _b;
40
+ if (!(t instanceof graphql_1.GraphQLEnumType)) {
41
+ return;
42
+ }
43
+ const name = t.toString();
44
+ if (name !== "Permission") {
45
+ return;
46
+ }
47
+ (_b = (_a = t.astNode) === null || _a === void 0 ? void 0 : _a.values) === null || _b === void 0 ? void 0 : _b.forEach(value => {
48
+ permissions.push(value.name.value);
49
+ });
50
+ });
51
+ return permissions;
52
+ };
53
+ const migratePermissions = async (permissions, serverAddress) => {
54
+ const managementClient = await (0, client_1.newManagementClient)({ serverAddress });
55
+ const existingPermissions = (await managementClient.getScopes()).filter(permission => !permission.startsWith("FRAYM_"));
56
+ console.log("existingPermissions", existingPermissions);
57
+ const permissionsToCreate = permissions.filter(permission => !existingPermissions.includes(permission));
58
+ const permissionsToDelete = existingPermissions.filter(permission => !permissions.includes(permission));
59
+ if (permissionsToCreate.length > 0) {
60
+ console.log(`Creating ${permissionsToCreate.length} permissions: ${permissionsToCreate}...`);
61
+ for (let i = 0; i < permissionsToCreate.length; i++) {
62
+ console.log("i", i);
63
+ await managementClient.createScope(permissionsToCreate[i]);
64
+ }
65
+ console.log(`Created ${permissionsToCreate.length} permissions`);
66
+ }
67
+ if (permissionsToDelete.length > 0) {
68
+ console.log(`Removing ${permissionsToDelete.length} permissions: ${permissionsToDelete}...`);
69
+ for (let i = 0; i < permissionsToDelete.length; i++) {
70
+ console.log("i", i);
71
+ await managementClient.deleteScope(permissionsToDelete[i]);
72
+ }
73
+ console.log(`Removed ${permissionsToDelete.length} permissions`);
74
+ }
75
+ };
76
+ run();
@@ -0,0 +1,7 @@
1
+ export interface ClientConfig {
2
+ serverAddress: string;
3
+ keepaliveInterval?: number;
4
+ keepaliveTimeout?: number;
5
+ }
6
+ export declare const getEnvConfig: () => ClientConfig;
7
+ export declare const useConfigDefaults: (config?: ClientConfig) => Required<ClientConfig>;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useConfigDefaults = exports.getEnvConfig = void 0;
4
+ const dotenv_1 = require("dotenv");
5
+ const getEnvConfig = () => {
6
+ var _a;
7
+ (0, dotenv_1.config)();
8
+ const serverAddress = (_a = process.env.AUTH_SERVER_ADDRESS) !== null && _a !== void 0 ? _a : "";
9
+ let keepaliveInterval;
10
+ let keepaliveTimeout;
11
+ const keepaliveIntervalString = process.env.AUTH_CONNECTION_KEEPALIVE_INTERVAL;
12
+ const keepaliveTimeoutString = process.env.AUTH_CONNECTION_KEEPALIVE_INTERVAL;
13
+ if (keepaliveIntervalString) {
14
+ keepaliveInterval = parseInt(keepaliveIntervalString, 10);
15
+ }
16
+ if (keepaliveTimeoutString) {
17
+ keepaliveTimeout = parseInt(keepaliveTimeoutString, 10);
18
+ }
19
+ return {
20
+ serverAddress,
21
+ keepaliveInterval,
22
+ keepaliveTimeout,
23
+ };
24
+ };
25
+ exports.getEnvConfig = getEnvConfig;
26
+ const useConfigDefaults = (config) => {
27
+ var _a, _b;
28
+ if (!config) {
29
+ config = (0, exports.getEnvConfig)();
30
+ }
31
+ return {
32
+ serverAddress: config.serverAddress,
33
+ keepaliveTimeout: (_a = config.keepaliveTimeout) !== null && _a !== void 0 ? _a : 3 * 1000,
34
+ keepaliveInterval: (_b = config.keepaliveInterval) !== null && _b !== void 0 ? _b : 40 * 1000,
35
+ };
36
+ };
37
+ exports.useConfigDefaults = useConfigDefaults;
@@ -0,0 +1,2 @@
1
+ export * from "./management/client";
2
+ export { ClientConfig } from "./config/config";
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./management/client"), exports);
@@ -0,0 +1,13 @@
1
+ import { ClientConfig } from "../config/config";
2
+ import { Role } from "./getRoles";
3
+ import { UpsertRoleScope } from "./upsertRole";
4
+ export interface ManagementClient {
5
+ createScope: (name: string, clientId?: string) => Promise<void>;
6
+ deleteScope: (name: string, clientId?: string) => Promise<void>;
7
+ getScopes: (clientId?: string) => Promise<string[]>;
8
+ upsertRole: (tenantId: string, id: string, allowedScopes: UpsertRoleScope[]) => Promise<void>;
9
+ deleteRole: (tenantId: string, id: string) => Promise<void>;
10
+ getRoles: (tenantId: string) => Promise<Role[]>;
11
+ close: () => Promise<void>;
12
+ }
13
+ export declare const newManagementClient: (config?: ClientConfig) => Promise<ManagementClient>;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.newManagementClient = void 0;
4
+ const auth_proto_1 = require("@fraym/auth-proto");
5
+ const grpc_js_1 = require("@grpc/grpc-js");
6
+ const config_1 = require("../config/config");
7
+ const createScope_1 = require("./createScope");
8
+ const deleteRole_1 = require("./deleteRole");
9
+ const deleteScope_1 = require("./deleteScope");
10
+ const getRoles_1 = require("./getRoles");
11
+ const getScopes_1 = require("./getScopes");
12
+ const upsertRole_1 = require("./upsertRole");
13
+ const newManagementClient = async (config) => {
14
+ config = (0, config_1.useConfigDefaults)(config);
15
+ const serviceClient = new auth_proto_1.ManagementServiceClient(config.serverAddress, grpc_js_1.credentials.createInsecure(), {
16
+ "grpc.keepalive_time_ms": config.keepaliveInterval,
17
+ "grpc.keepalive_timeout_ms": config.keepaliveTimeout,
18
+ "grpc.keepalive_permit_without_calls": 1,
19
+ });
20
+ const createScope = async (name, clientId = "") => {
21
+ await (0, createScope_1.createNewScope)(name, clientId, serviceClient);
22
+ };
23
+ const deleteScope = async (name, clientId = "") => {
24
+ await (0, deleteScope_1.deleteExistingScope)(name, clientId, serviceClient);
25
+ };
26
+ const getScopes = async (clientId = "") => {
27
+ return await (0, getScopes_1.getAllScopes)(clientId, serviceClient);
28
+ };
29
+ const upsertRole = async (tenantId, id, allowedScopes) => {
30
+ return await (0, upsertRole_1.createOrUpdateRole)(tenantId, id, allowedScopes, serviceClient);
31
+ };
32
+ const deleteRole = async (tenantId, id) => {
33
+ return await (0, deleteRole_1.deleteExistingRole)(tenantId, id, serviceClient);
34
+ };
35
+ const getRoles = async (tenantId) => {
36
+ return await (0, getRoles_1.getAllRoles)(tenantId, serviceClient);
37
+ };
38
+ const close = async () => {
39
+ serviceClient.close();
40
+ };
41
+ return {
42
+ createScope,
43
+ deleteScope,
44
+ getScopes,
45
+ upsertRole,
46
+ deleteRole,
47
+ getRoles,
48
+ close,
49
+ };
50
+ };
51
+ exports.newManagementClient = newManagementClient;
@@ -0,0 +1,2 @@
1
+ import { ManagementServiceClient } from "@fraym/auth-proto";
2
+ export declare const createNewScope: (name: string, clientId: string, serviceClient: ManagementServiceClient) => Promise<void>;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createNewScope = void 0;
4
+ const createNewScope = async (name, clientId, serviceClient) => {
5
+ return new Promise((resolve, reject) => {
6
+ serviceClient.createScope({
7
+ name,
8
+ clientId,
9
+ }, error => {
10
+ if (error) {
11
+ reject(error.message);
12
+ return;
13
+ }
14
+ resolve();
15
+ });
16
+ });
17
+ };
18
+ exports.createNewScope = createNewScope;
@@ -0,0 +1,2 @@
1
+ import { ManagementServiceClient } from "@fraym/auth-proto";
2
+ export declare const deleteExistingRole: (tenantId: string, id: string, serviceClient: ManagementServiceClient) => Promise<void>;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deleteExistingRole = void 0;
4
+ const deleteExistingRole = async (tenantId, id, serviceClient) => {
5
+ return new Promise((resolve, reject) => {
6
+ serviceClient.deleteRole({
7
+ tenantId,
8
+ id,
9
+ }, error => {
10
+ if (error) {
11
+ reject(error.message);
12
+ return;
13
+ }
14
+ resolve();
15
+ });
16
+ });
17
+ };
18
+ exports.deleteExistingRole = deleteExistingRole;
@@ -0,0 +1,2 @@
1
+ import { ManagementServiceClient } from "@fraym/auth-proto";
2
+ export declare const deleteExistingScope: (name: string, clientId: string, serviceClient: ManagementServiceClient) => Promise<void>;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deleteExistingScope = void 0;
4
+ const deleteExistingScope = async (name, clientId, serviceClient) => {
5
+ return new Promise((resolve, reject) => {
6
+ serviceClient.deleteScope({
7
+ name,
8
+ clientId,
9
+ }, error => {
10
+ if (error) {
11
+ reject(error.message);
12
+ return;
13
+ }
14
+ resolve();
15
+ });
16
+ });
17
+ };
18
+ exports.deleteExistingScope = deleteExistingScope;
@@ -0,0 +1,10 @@
1
+ import { ManagementServiceClient } from "@fraym/auth-proto";
2
+ export interface Role {
3
+ id: string;
4
+ allowedScopes: RoleScope[];
5
+ }
6
+ export interface RoleScope {
7
+ clientId: string;
8
+ scopeName: string;
9
+ }
10
+ export declare const getAllRoles: (tenantId: string, serviceClient: ManagementServiceClient) => Promise<Role[]>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getAllRoles = void 0;
4
+ const getAllRoles = async (tenantId, serviceClient) => {
5
+ return new Promise((resolve, reject) => {
6
+ serviceClient.getRoles({
7
+ tenantId,
8
+ }, (error, response) => {
9
+ if (error) {
10
+ reject(error.message);
11
+ return;
12
+ }
13
+ resolve(response.roles);
14
+ });
15
+ });
16
+ };
17
+ exports.getAllRoles = getAllRoles;
@@ -0,0 +1,2 @@
1
+ import { ManagementServiceClient } from "@fraym/auth-proto";
2
+ export declare const getAllScopes: (clientId: string, serviceClient: ManagementServiceClient) => Promise<string[]>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getAllScopes = void 0;
4
+ const getAllScopes = async (clientId, serviceClient) => {
5
+ return new Promise((resolve, reject) => {
6
+ serviceClient.getScopes({
7
+ clientId,
8
+ }, (error, response) => {
9
+ if (error) {
10
+ reject(error.message);
11
+ return;
12
+ }
13
+ resolve(response.scopes);
14
+ });
15
+ });
16
+ };
17
+ exports.getAllScopes = getAllScopes;
@@ -0,0 +1,6 @@
1
+ import { ManagementServiceClient } from "@fraym/auth-proto";
2
+ export interface UpsertRoleScope {
3
+ scopeName: string;
4
+ clientId?: string;
5
+ }
6
+ export declare const createOrUpdateRole: (tenantId: string, id: string, allowedScopes: UpsertRoleScope[], serviceClient: ManagementServiceClient) => Promise<void>;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createOrUpdateRole = void 0;
4
+ const createOrUpdateRole = async (tenantId, id, allowedScopes, serviceClient) => {
5
+ return new Promise((resolve, reject) => {
6
+ serviceClient.upsertRole({
7
+ tenantId,
8
+ id,
9
+ allowedScopes: allowedScopes.map(scope => {
10
+ var _a;
11
+ return {
12
+ scopeName: scope.scopeName,
13
+ clientId: (_a = scope.clientId) !== null && _a !== void 0 ? _a : "",
14
+ };
15
+ }),
16
+ }, error => {
17
+ if (error) {
18
+ reject(error.message);
19
+ return;
20
+ }
21
+ resolve();
22
+ });
23
+ });
24
+ };
25
+ exports.createOrUpdateRole = createOrUpdateRole;
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@fraym/auth",
3
+ "version": "0.1.0",
4
+ "license": "UNLICENSED",
5
+ "homepage": "https://github.com/fraym/auth-nodejs",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/fraym/auth-nodejs.git"
9
+ },
10
+ "description": "nodejs client implementation for our auth service",
11
+ "scripts": {
12
+ "test": "echo \"Error: no test specified\" && exit 0",
13
+ "format": "prettier --write \"**/*.{ts,tsx,json}\"",
14
+ "lint": "prettier --check \"**/*.{ts,tsx,json}\"",
15
+ "build": "npm run clean && tsc && chmod +x dist/cmd/auth.js",
16
+ "clean": "rm -rf dist",
17
+ "prepublishOnly": "npm test && npm run lint && npm run build",
18
+ "preversion": "npm run lint",
19
+ "cmd": "dist/cmd/auth.js"
20
+ },
21
+ "files": [
22
+ "dist/**/*"
23
+ ],
24
+ "main": "dist/index.js",
25
+ "types": "dist/index.d.ts",
26
+ "bin": {
27
+ "auth": "dist/cmd/auth.js"
28
+ },
29
+ "dependencies": {
30
+ "@fraym/auth-proto": "^0.4.0",
31
+ "@graphql-tools/graphql-file-loader": "^7.5.11",
32
+ "@graphql-tools/load": "^7.8.6",
33
+ "@grpc/grpc-js": "1.7.2",
34
+ "dotenv": "^16.0.3",
35
+ "graphql": "^16.6.0",
36
+ "yargs": "^17.6.2"
37
+ },
38
+ "devDependencies": {
39
+ "@becklyn/prettier": "^1.0.2",
40
+ "@types/uuid": "^8.3.4",
41
+ "@types/yargs": "^17.0.13",
42
+ "prettier": "^2.7.1",
43
+ "typescript": "^4.8.4",
44
+ "uuid": "^9.0.0"
45
+ },
46
+ "prettier": "@becklyn/prettier"
47
+ }