Skip to content

Commit 5682e50

Browse files
DaleHerringDale Herring
andauthored
DEV-188 - create/edit organization fixes to support type id (#22)
* DEV-188 - create/edit organization fixes to support type id * DEV-188 code clean up for pr comments * DEV-188 - cache org types call * DEV-188 - rename prefixes and update error msg * DEV-188 - move parse for orgtypes * DEV-188 - add dev-tech as code owners * DEV-188 - changes to create/edit organization endpoints * DEV-188 - addressing type changes from an ever changing backend * DEV-188 - clone fix * DEV-188 - add interpreter, fix tests Co-authored-by: Dale Herring <dale.herring@ruralsourcing.com>
1 parent 4b9e903 commit 5682e50

6 files changed

Lines changed: 103 additions & 34 deletions

File tree

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# Changlog
22

3+
## v2.0.0 - 02/23/2021
4+
5+
----------------
6+
7+
### Changes
8+
9+
- Create organization endpoint now takes in second parameter for user-friendly type name
10+
- org_url is required
11+
12+
313
## v1.0.0 - 01/08/2021
414

515
-----------------

src/Algorithm.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,14 +231,26 @@ interface Organization {
231231
org_label: string;
232232
org_name: string;
233233
resource_type: string;
234+
type_id: string;
235+
org_url: string;
234236

235-
org_url?: string;
236237
external_id?: string;
237238
external_admin_group_id?: string;
238239
external_member_group_id?: string;
239240
self_link?: string;
240241
}
241242

243+
interface OrgTypes {
244+
id: string;
245+
name: string;
246+
}
247+
248+
enum OrgType {
249+
Basic = 'basic',
250+
Legacy = 'legacy',
251+
Pro = 'pro'
252+
}
253+
242254
interface AlgorithmVersionsList {
243255
marker: string;
244256
next_link: string;
@@ -275,4 +287,6 @@ export {
275287
AlgorithmBuildsList,
276288
AlgorithmSCMAuthorizationStatus,
277289
Organization,
290+
OrgTypes,
291+
OrgType
278292
};

src/AlgorithmiaClient.ts

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@ import { AlgorithmExecutable } from './AlgorithmExecutable';
33
import type { Input } from './ContentTypeHelper';
44
import { DataFile, DataDir } from './Data';
55
import { URLSearchParams } from 'url';
6+
import { Organization, OrgType, OrgTypes } from './Algorithm';
67

78
class AlgorithmiaClient {
89
private defaultApiAddress = 'https://api.algorithmia.com';
910
private algoPrefix = '/v1/algo';
1011
private algorithmsPrefix = '/v1/algorithms';
1112
private dataPrefix = '/v1/data';
1213
private scmPrefix = '/v1/scms';
13-
private organizationPrefix = '/v1/organizations';
14+
private organizationTypePrefix = '/v1/organization';
15+
private organizationsPrefix = '/v1/organizations';
16+
private typesMapList: OrgTypes[] = [];
1417
private key: string;
1518
private apiAddress: string;
1619
private httpClient: HttpClient;
@@ -200,24 +203,25 @@ class AlgorithmiaClient {
200203
* @param requestObject object payload
201204
* @return an organization object
202205
*/
203-
createOrganization(requestObject: Input) {
206+
async createOrganization(requestObject: Input, type: OrgType) {
204207
const contentType = 'application/json';
205208
return this.httpClient.post(
206-
this.apiAddress + this.organizationPrefix,
207-
requestObject,
209+
`${this.apiAddress}${this.organizationsPrefix}`,
210+
JSON.stringify(await this.organizationTypeIdChanger(requestObject, type)),
208211
contentType
209-
);
212+
);
210213
}
211214

212215
/**
213216
* Get an organization from this client
214217
* @param orgName the organization name
215218
* @return an organization object
216219
*/
217-
getOrganization(orgName: string) {
218-
return this.httpClient.get(
219-
this.apiAddress + this.organizationPrefix + '/' + orgName
220-
);
220+
async getOrganization(orgName: string) : Promise<Organization> {
221+
const organization: Organization = JSON.parse(await this.httpClient.get(
222+
`${this.apiAddress}${this.organizationsPrefix}/${orgName}`
223+
));
224+
return organization;
221225
}
222226

223227
/**
@@ -228,11 +232,44 @@ class AlgorithmiaClient {
228232
*/
229233
editOrganization(orgName: string, requestObject: Input) {
230234
return this.httpClient.put(
231-
this.apiAddress + this.organizationPrefix + '/' + orgName,
232-
JSON.stringify(requestObject)
235+
`${this.apiAddress}${this.organizationsPrefix}/${orgName}`,
236+
requestObject
233237
);
234238
}
235239

240+
clone(obj: Input) {
241+
return JSON.parse(JSON.stringify(obj));
242+
}
243+
244+
/**
245+
* Helper for swapping out the type_id value
246+
*/
247+
async organizationTypeIdChanger(requestObject: Input, type: OrgType) {
248+
const editedOrganization: Organization = this.clone(requestObject);
249+
let isSet = false;
250+
if (!this.typesMapList.length) {
251+
this.typesMapList = await this.getOrgTypes();
252+
}
253+
for (var typesMapObject of this.typesMapList) {
254+
if(type === typesMapObject.name) {
255+
editedOrganization.type_id = typesMapObject.id;
256+
isSet = true;
257+
break;
258+
};
259+
}
260+
if (!isSet) {
261+
throw new Error("No matching organization type found, should be one of 'legacy', 'basic', 'pro'");
262+
}
263+
return editedOrganization;
264+
}
265+
266+
/**
267+
* Get types uuid endpoint
268+
*/
269+
async getOrgTypes() {
270+
return JSON.parse(await this.httpClient.get(`${this.apiAddress}${this.organizationTypePrefix}/types`));
271+
}
272+
236273
/**
237274
* Initialize an DataFile object from this client
238275
* @param path to a data file, e.g., data://.my/foo/bar.txt

src/HttpClient.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,29 @@ class HttpClient {
3434

3535
async post(path: string, data: Input, contentType: string) {
3636
this.headers['Content-Type'] = contentType;
37+
const toString = (data: unknown) =>
38+
typeof data === 'string' ? data : JSON.stringify(data, null, 2)
3739
const response = await this.httpClient.post(
3840
path,
39-
JSON.stringify(data),
41+
toString(data),
4042
this.headers
4143
);
4244

4345
return response.readBody();
4446
}
4547

48+
async put(path: string, data: Input) {
49+
this.headers['Content-Type'] = 'application/json';
50+
const toString = (data: unknown) =>
51+
typeof data === 'string' ? data : JSON.stringify(data, null, 2)
52+
const response = await this.httpClient.put(
53+
path,
54+
toString(data),
55+
this.headers);
56+
57+
return response.readBody();
58+
}
59+
4660
async putJson(path: string, data: Json) {
4761
const response = await this.httpClient.put(
4862
path,
@@ -53,13 +67,6 @@ class HttpClient {
5367
return response.readBody();
5468
}
5569

56-
async put(path: string, data: string) {
57-
this.headers['Content-Type'] = 'application/json';
58-
const response = await this.httpClient.put(path, data, this.headers);
59-
60-
return response.readBody();
61-
}
62-
6370
async delete(path: string) {
6471
const response = await this.httpClient.del(path, this.headers);
6572

test/AlgorithmExecutable.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ describe('Localisation initialization', () => {
1414
.algo('nlb/Hello/1.0.0')
1515
.pipe('foo');
1616

17-
expect(result).toBe('Hello "foo"');
17+
expect(result).toBe('Hello foo');
1818
});
1919
});
2020
});

test/AlgorithmiaClient.test.ts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
AlgorithmBuildsList,
77
AlgorithmSCMAuthorizationStatus,
88
Organization,
9+
OrgType
910
} from '../src/Algorithm';
1011

1112
describe('Localisation initialization', () => {
@@ -143,30 +144,28 @@ describe('Localisation initialization', () => {
143144

144145
describe('organization get organization', () => {
145146
it('gets an organization', async () => {
146-
const organization: Organization = JSON.parse(
147+
const organization: Organization =
147148
await Algorithmia.getClient(
148149
process.env.ALGORITHMIA_ADMIN_API_KEY,
149150
process.env.ALGORITHMIA_TEST_ADDRESS
150-
).getOrganization('a_myOrg15')
151-
);
151+
).getOrganization('MyOrg1614039696593');
152152

153-
expect(organization.org_email).toBe('a_myOrg15@algo.com');
153+
expect(organization.org_name).toBe('MyOrg1614039696593');
154154
});
155155
});
156156

157157
describe('organization edit call', () => {
158158
it('edits for organization', async () => {
159+
const organization: Organization =
160+
await Algorithmia.getClient(
161+
process.env.ALGORITHMIA_ADMIN_API_KEY,
162+
process.env.ALGORITHMIA_TEST_ADDRESS
163+
).getOrganization('MyOrg1614118479820');
164+
organization.org_email = 'SomeOtherEmail@HowDoYouEven.com'
159165
const response = await Algorithmia.getClient(
160166
process.env.ALGORITHMIA_ADMIN_API_KEY,
161167
process.env.ALGORITHMIA_TEST_ADDRESS
162-
).editOrganization('MyOrg1606332498213', {
163-
org_contact_name: 'some owner',
164-
org_email: 'SomeEmail@Whatsittoyou.com',
165-
org_label: 'myLabel',
166-
type_id: '3d40e3b0-d82a-11ea-9a3c-0ee5e2d35097',
167-
resource_type: 'organization',
168-
id: '3d9a9f41-d82a-11ea-9a3c-0ee5e2d35097',
169-
});
168+
).editOrganization(organization.org_name, JSON.stringify(organization));
170169
expect(response).toBe('');
171170
});
172171
});
@@ -178,13 +177,15 @@ describe('Localisation initialization', () => {
178177
org_email: 'SomeEmail@Whatsittoyou.com',
179178
org_label: 'myLabel',
180179
org_name: 'MyOrg' + Date.now(),
180+
org_url: 'https://algorithmia.com',
181+
resource_type: 'organization'
181182
};
182183

183184
const organization: Organization = JSON.parse(
184185
await Algorithmia.getClient(
185186
process.env.ALGORITHMIA_ADMIN_API_KEY,
186187
process.env.ALGORITHMIA_TEST_ADDRESS
187-
).createOrganization(testOrganization)
188+
).createOrganization(testOrganization, OrgType.Legacy)
188189
);
189190
expect(organization.org_name).toBe(testOrganization.org_name);
190191
});

0 commit comments

Comments
 (0)