Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
# Conflicts:
#	AdminWebApp/src/api/client.ts
#	AdminWebApp/src/pages/Home.vue
#	AdminWebApp/src/translations.ts
#	src/data_access_layer/repositories/data_warehouse/data/node_repository.ts
#	src/data_access_layer/repositories/repository.ts
#	src/domain_objects/access_management/user.ts
#	src/tests/data_warehouse/data/timeseries/timeseries_entry_repository.spec.ts
  • Loading branch information
DnOberon committed May 24, 2022
2 parents c3c7455 + 7efe886 commit b32116a
Show file tree
Hide file tree
Showing 60 changed files with 2,218 additions and 362 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ profile-logs
/private-key.key
/src/tests/test-data.json
/src/tests/test-data.csv
/src/tests/private-key.pem
114 changes: 112 additions & 2 deletions AdminWebApp/src/api/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
ChangelistApprovalT,
ContainerAlertT,
TypeMappingUpgradePayloadT,
NodeTransformationT,
NodeTransformationT, CreateServiceUserPayloadT, ServiceUserPermissionSetT,
} from '@/api/types';
import {RetrieveJWT} from '@/auth/authentication_service';
import {UserT} from '@/auth/types';
Expand Down Expand Up @@ -130,7 +130,7 @@ export class Client {
});
}

async updateContainerFromImport(containerID: string, owlFile: File | null, owlFilePath: string): Promise<string> {
async updateContainerFromImport(containerID: string, owlFile: File | null, owlFilePath: string, name?: string): Promise<string> {
const config: {[key: string]: any} = {};
config.headers = {'Access-Control-Allow-Origin': '*'};

Expand All @@ -151,6 +151,10 @@ export class Client {
formData.append('path', owlFilePath);
}

if (name) {
formData.append('name', name);
}

const resp: AxiosResponse = await axios.put(
buildURL(this.config?.rootURL!, {path: `containers/import/${containerID}`}),
formData,
Expand Down Expand Up @@ -340,6 +344,75 @@ export class Client {
return this.delete(`/users/keys/${keyID}`);
}

listKeyPairsForServiceUser(containerID: string, serviceUserID: string): Promise<KeyPairT[]> {
return this.get<KeyPairT[]>(`/containers/${containerID}/service-users/${serviceUserID}/keys`);
}

generateKeyPairForServiceUser(containerID: string, serviceUserID: string): Promise<KeyPairT> {
return this.post<KeyPairT>(`/containers/${containerID}/service-users/${serviceUserID}/keys`, undefined);
}

deleteKeyPairForServiceUser(containerID: string, serviceUserID: string, keyID: string): Promise<boolean> {
return this.delete(`/containers/${containerID}/service-users/${serviceUserID}/keys/${keyID}`);
}


createServiceUser(containerID: string, payload: CreateServiceUserPayloadT): Promise<UserT> {
return this.post<UserT>(`/containers/${containerID}/service-users`, payload);
}

listServiceUsers(containerID: string): Promise<UserT[]> {
return this.get<UserT[]>(`/containers/${containerID}/service-users`)
}

deleteServiceUser(containerID: string, userID: string): Promise<boolean> {
return this.delete(`/containers/${containerID}/service-users/${userID}`);
}

getServiceUsersPermissions(containerID: string, userID: string): Promise<ServiceUserPermissionSetT> {
return new Promise((resolve, reject) => {
this.getRaw<string[][]>(`/containers/${containerID}/service-users/${userID}/permissions`)
.then(results => {
const set: ServiceUserPermissionSetT = {
containers: [],
ontology: [],
users: [],
data: []
}

results.forEach(result => {
if(result.length != 3) return

switch(result[1]) {
case 'containers': {
set.containers.push(result[2])
break;
}
case 'ontology': {
set.ontology.push(result[2])
break;
}
case 'data': {
set.data.push(result[2])
break;
}
case 'users': {
set.users.push(result[2])
break;
}
}
})

resolve(set)
})
.catch(e => reject(e))
})
}

setServiceUsersPermissions(containerID: string, userID: string, set: ServiceUserPermissionSetT): Promise<boolean> {
return this.put<boolean>(`/containers/${containerID}/service-users/${userID}/permissions`, set)
}

listMetatypeRelationships(
containerID: string,
{
Expand Down Expand Up @@ -465,6 +538,10 @@ export class Client {
return this.post<DataSourceT>(`/containers/${containerID}/import/datasources`, dataSource);
}

updateDataSource(containerID: string, dataSource: DataSourceT): Promise<DataSourceT> {
return this.put<DataSourceT>(`/containers/${containerID}/import/datasources/${dataSource.id}`, dataSource);
}

createTypeMappingTransformation(
containerID: string,
dataSourceID: string,
Expand Down Expand Up @@ -962,6 +1039,39 @@ export class Client {
});
}

private async getRaw<T>(uri: string, queryParams?: {[key: string]: any}): Promise<T> {
const config: AxiosRequestConfig = {};
config.headers = {'Access-Control-Allow-Origin': '*'};
config.validateStatus = () => {
return true;
};

if (this.config?.auth_method === 'token') {
config.headers = {Authorization: `Bearer ${RetrieveJWT()}`};
}

if (this.config?.auth_method === 'basic') {
config.auth = {username: this.config.username, password: this.config.password} as AxiosBasicCredentials;
}

let url: string;

if (queryParams) {
url = buildURL(this.config?.rootURL!, {path: uri, queryParams: queryParams!});
} else {
url = buildURL(this.config?.rootURL!, {path: uri});
}

// `${this.config?.rootURL}${uri}
const resp: AxiosResponse = await axios.get(url, config);

return new Promise<T>((resolve, reject) => {
if (resp.status < 200 || resp.status > 299) reject(resp.data);

resolve(resp.data as T);
});
}

// getNoData will return true if the response code falls between 200-299
private async getNoData(uri: string, queryParams?: {[key: string]: any}): Promise<boolean> {
const config: AxiosRequestConfig = {};
Expand Down
11 changes: 11 additions & 0 deletions AdminWebApp/src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,17 @@ export type AssignRolePayloadT = {
role_name: string;
};

export type CreateServiceUserPayloadT = {
display_name: string;
}

export type ServiceUserPermissionSetT = {
containers: string[];
ontology: string[];
data: string[];
users: string[];
}

export type ImportDataT = {
id: number;
data_source_id: string;
Expand Down
43 changes: 34 additions & 9 deletions AdminWebApp/src/components/accessManagement/createApiKeyDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,37 +18,62 @@
<p>{{returnedKey.secret_raw}}</p>
</v-alert>
<v-row>
<v-col :cols="12">
<v-col :cols="12" v-if="serviceUserID === null">
<p>{{$t('createApiKey.description')}}</p>
</v-col>
<v-col :cols="12" v-else>
<p>{{$t('createApiKey.descriptionService')}}</p>
</v-col>
</v-row>
</v-card-text>

<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="dialog = false; returnedKey = null" >{{$t("createApiKey.cancel")}}</v-btn>
<v-btn color="blue darken-1" text @click="generateApiKey">{{$t("createApiKey.create")}}</v-btn>
<div v-if="returnedKey !== null">
<v-btn color="blue darken-1" text @click="dialog = false; returnedKey = null" >{{$t("createApiKey.close")}}</v-btn>
</div>
<div v-else>
<v-btn color="blue darken-1" text @click="dialog = false; returnedKey = null" >{{$t("createApiKey.cancel")}}</v-btn>
<v-btn color="blue darken-1" text @click="generateApiKey">{{$t("createApiKey.create")}}</v-btn>
</div>

</v-card-actions>
</v-card>
</v-dialog>
</template>

<script lang="ts">
import {Component, Vue} from "vue-property-decorator";
import {Component, Prop, Vue} from "vue-property-decorator";
import {KeyPairT} from "@/api/types";
@Component
export default class CreateApiKeyDialog extends Vue {
@Prop({required: false})
containerID?: string
@Prop({required: false})
serviceUserID?: string
errorMessage = ""
dialog = false
returnedKey: KeyPairT | null = null
generateApiKey() {
this.$client.generateKeyPairForUser()
.then(key => {
this.returnedKey = key
})
.catch((e) => this.errorMessage = e)
if(this.serviceUserID) {
this.$client.generateKeyPairForServiceUser(this.containerID!, this.serviceUserID)
.then(key => {
this.returnedKey = key
this.$emit('apiKeyCreated')
})
.catch((e) => this.errorMessage = e)
} else {
this.$client.generateKeyPairForUser()
.then(key => {
this.returnedKey = key
this.$emit('apiKeyCreated')
})
.catch((e) => this.errorMessage = e)
}
}
}
</script>
27 changes: 21 additions & 6 deletions AdminWebApp/src/components/accessManagement/deleteApiKeyDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ import {KeyPairT} from "@/api/types";
@Component
export default class DeleteApiKeyDialog extends Vue {
@Prop({required: false})
containerID?: string
@Prop({required: false})
serviceUserID?: string
@Prop({required: true})
readonly keyPair!: KeyPairT
Expand All @@ -58,12 +64,21 @@ export default class DeleteApiKeyDialog extends Vue {
}
deleteApiKey() {
this.$client.deleteKeyPairForUser(this.keyPair.key)
.then(() => {
this.dialog = false
this.$emit('apiKeyDeleted')
})
.catch(e => this.errorMessage = e)
if(this.serviceUserID) {
this.$client.deleteKeyPairForServiceUser(this.containerID!, this.serviceUserID, this.keyPair.key)
.then(() => {
this.dialog = false
this.$emit('apiKeyDeleted')
})
.catch(e => this.errorMessage = e)
} else {
this.$client.deleteKeyPairForUser(this.keyPair.key)
.then(() => {
this.dialog = false
this.$emit('apiKeyDeleted')
})
.catch(e => this.errorMessage = e)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<template>
<v-dialog v-model="dialog" @click:outside="dialog = false; reset()" max-width="60%">
<template v-slot:activator="{ on }">
<v-icon
v-if="icon"
small
class="mr-2"
v-on="on"
>mdi-card-plus</v-icon>
<v-btn v-if="!icon" color="primary" dark class="mt-2" v-on="on">{{$t("createServiceUser.createServiceUser")}}</v-btn>
</template>

<v-card class="pt-1 pb-3 px-2">
<v-card-title>
<span class="headline text-h3">{{$t('createServiceUser.createTitle')}}</span>
</v-card-title>
<v-card-text>
<error-banner :message="errorMessage"></error-banner>
<v-row>
<v-col :cols="12">

<v-form
ref="form"
v-model="valid"
>
<v-text-field
v-model="name"
:rules="[v => !!v || $t('createServiceUser.nameMissing')]"
required
>
<template v-slot:label>{{$t('createServiceUser.name')}} <small style="color:red" >*</small></template>
</v-text-field>
</v-form>
<p><span style="color:red">*</span> = {{$t('createServiceUser.requiredField')}}</p>
</v-col>
</v-row>
</v-card-text>

<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="dialog = false; reset()" >{{$t("createServiceUser.cancel")}}</v-btn>
<v-btn color="blue darken-1" :disabled="!valid" text @click="createServiceUser()">{{$t("createServiceUser.save")}}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>

<script lang="ts">
import {Component, Prop, Vue} from 'vue-property-decorator'
@Component
export default class CreateServiceUser extends Vue {
@Prop({required: true})
containerID!: string;
@Prop({required: false})
readonly icon!: boolean
errorMessage = ""
dialog = false
name = ""
valid = false
createServiceUser() {
this.$client.createServiceUser(this.containerID, {display_name: this.name})
.then(result => {
if(!result) {
this.errorMessage = this.$t('createServiceUser.errorCreatingAPI') as string
} else {
this.dialog = false
this.$emit('serviceUserCreated', result)
this.reset()
}
})
.catch(e => this.errorMessage = this.$t('createServiceUser.errorCreatingAPI') as string + e)
}
reset() {
this.name = ""
}
}
</script>
Loading

0 comments on commit b32116a

Please sign in to comment.