Skip to content

Commit a99b35d

Browse files
author
Istemi Ekin Akkus
authored
Merge pull request #37 from knix-microfunctions/feature/delete_account
Feature/delete account
2 parents f8a6672 + b76b2b1 commit a99b35d

File tree

21 files changed

+611
-148
lines changed

21 files changed

+611
-148
lines changed

FunctionWorker/python/DataLayerClient.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
class DataLayerClient:
2929

30-
def __init__(self, locality=1, sid=None, wid=None, suid=None, is_wf_private=False, for_mfn=False, connect="127.0.0.1:4998", init_tables=False):
30+
def __init__(self, locality=1, sid=None, wid=None, suid=None, is_wf_private=False, for_mfn=False, connect="127.0.0.1:4998", init_tables=False, drop_keyspace=False):
3131
self.dladdress = connect
3232

3333
if for_mfn:
@@ -68,6 +68,9 @@ def __init__(self, locality=1, sid=None, wid=None, suid=None, is_wf_private=Fals
6868
if init_tables:
6969
self._initialize_tables()
7070

71+
if drop_keyspace:
72+
self._drop_keyspace()
73+
7174
def _initialize_tables(self):
7275
replication_factor = 3
7376
# just need the local instance
@@ -87,6 +90,12 @@ def _initialize_tables(self):
8790
print("Could not initialize tables: " + str(exc))
8891
raise
8992

93+
def _drop_keyspace(self):
94+
try:
95+
self.datalayer.dropKeyspace(self.keyspace, self.locality)
96+
except Thrift.TException as exc:
97+
print("Could not drop keyspace: " + str(exc))
98+
raise
9099

91100
def connect(self):
92101
retry = 0.5 #s

FunctionWorker/python/MicroFunctionsAPI.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -82,25 +82,16 @@ def __init__(self, uid, sid, wid, funcstatename, key, publication_utils, is_sess
8282
#self._logger.debug("[MicroFunctionsAPI] init done.")
8383

8484
def ping(self, num):
85-
self._logger.info("ping:" + str(num))
85+
self._logger.info("ping: " + str(num))
8686
output = num
8787
return 'pong ' + str(output)
8888

89-
def get_privileged_data_layer_client(self, suid=None, keyspace=None, tablename=None, maptablename=None, settablename=None, countertablename=None, init_tables=False):
89+
def get_privileged_data_layer_client(self, suid=None, sid=None, init_tables=False, drop_keyspace=False):
9090
if self._is_privileged:
9191
if suid is not None:
92-
return DataLayerClient(locality=1, suid=suid, connect=self._datalayer, init_tables=init_tables)
93-
elif keyspace is not None and tablename is not None:
94-
dlc = DataLayerClient(locality=1, for_mfn=True, connect=self._datalayer)
95-
dlc.keyspace = keyspace
96-
dlc.tablename = tablename
97-
if maptablename is not None:
98-
dlc.maptablename = maptablename
99-
if settablename is not None:
100-
dlc.settablename = settablename
101-
if countertablename is not None:
102-
dlc.countertablename = countertablename
103-
return dlc
92+
return DataLayerClient(locality=1, suid=suid, connect=self._datalayer, init_tables=init_tables, drop_keyspace=drop_keyspace)
93+
elif sid is not None:
94+
return DataLayerClient(locality=1, for_mfn=True, sid=sid, connect=self._datalayer, drop_keyspace=drop_keyspace)
10495
return None
10596

10697
def update_metadata(self, metadata_name, metadata_value, is_privileged_metadata=False):

GUI/app/pages/profile/ProfileCtrl.js

Lines changed: 207 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525
/** @ngInject */
2626
function ProfileCtrl($scope, $http, sharedProperties, sharedData, toastr, $cookies, $uibModal) {
27-
2827
var urlPath = sharedProperties.getUrlPath();
2928

3029
$scope.workflows = sharedData.getWorkflows();
@@ -65,6 +64,35 @@
6564
document.location.href="auth.html";
6665
}
6766

67+
$scope.removeAccount = function() {
68+
69+
var password = $("#currentPassword").val();
70+
71+
if (!password) {
72+
$scope.errorMessage = "Please enter your password."
73+
$uibModal.open({
74+
animation: true,
75+
scope: $scope,
76+
templateUrl: 'app/pages/workflows/modals/errorModal.html',
77+
size: 'md',
78+
});
79+
return;
80+
} else {
81+
$uibModal.open({
82+
animation: true,
83+
scope: $scope,
84+
templateUrl: 'app/pages/profile/modals/deleteAccountModal.html',
85+
size: 'md',
86+
});
87+
}
88+
};
89+
90+
$scope.undeployAllWorkflows = function() {
91+
var password = $("#currentPassword").val();
92+
$("#currentPassword").val("");
93+
checkDeployedWorkflows(password);
94+
};
95+
6896
$scope.clearPassword = function() {
6997
$("#currentPassword").val("");
7098
}
@@ -120,7 +148,6 @@
120148
}
121149

122150
$http(req).then(function successCallback(response) {
123-
124151
if (response.data.status=="success") {
125152
console.log("Message:" + response.data.data.message);
126153
$cookies.put('name', newName);
@@ -154,8 +181,184 @@
154181
templateUrl: 'app/pages/workflows/modals/errorModal.html',
155182
size: 'md',
156183
});
184+
});
185+
}
186+
187+
function deleteAccount(password) {
188+
189+
if ($scope.workflowUndeploymentModal) {
190+
$scope.workflowUndeploymentModal.dismiss();
191+
}
192+
193+
var req = {
194+
method: 'POST',
195+
url: urlPath,
196+
headers: {
197+
'Content-Type': 'application/json'
198+
},
199+
200+
data: JSON.stringify({ "action" : "deleteAccount", "data" : { "user" : { "password": password, "token" : token } } })
201+
202+
}
203+
204+
$http(req).then(function successCallback(response) {
205+
206+
if (response.data.status=="success") {
207+
console.log("Message:" + response.data.data.message);
208+
$scope.logOut();
209+
210+
} else {
211+
console.log("Failure status returned by deleteAccount request");
212+
console.log("Message:" + response.data.data.message);
213+
$scope.errorMessage = response.data.data.message;
214+
$uibModal.open({
215+
animation: true,
216+
scope: $scope,
217+
templateUrl: 'app/pages/workflows/modals/errorModal.html',
218+
size: 'md',
219+
});
220+
221+
}
222+
}, function errorCallback(response) {
223+
console.log("Error occurred during deleteAccount request");
224+
console.log("Response:" + response);
225+
if (response.statusText) {
226+
$scope.errorMessage = response.statusText;
227+
} else {
228+
$scope.errorMessage = response;
229+
}
230+
$uibModal.open({
231+
animation: true,
232+
scope: $scope,
233+
templateUrl: 'app/pages/workflows/modals/errorModal.html',
234+
size: 'md',
235+
});
157236

158237
});
238+
239+
}
240+
241+
function checkDeployedWorkflows(password) {
242+
243+
var req = {
244+
method: 'POST',
245+
url: urlPath,
246+
headers: {
247+
'Content-Type': 'application/json'
248+
},
249+
data: JSON.stringify({ "action" : "getWorkflows", "data" : { "user" : { "token" : token } } })
250+
}
251+
252+
$http(req).then(function successCallback(response) {
253+
254+
if (response.data.status=="success") {
255+
256+
$scope.workflows = response.data.data.workflows;
257+
sharedData.setWorkflows(response.data.data.workflows);
258+
var deployedWorkflows = false;
259+
for (var i=0;i<$scope.workflows.length;++i) {
260+
if ($scope.workflows[i].status=="deployed") {
261+
undeployWorkflow(i, password);
262+
deployedWorkflows = true;
263+
break;
264+
}
265+
}
266+
if (!deployedWorkflows) {
267+
deleteAccount(password);
268+
}
269+
270+
} else {
271+
console.log("Failure status returned by getWorkflows");
272+
console.log("Message:" + response.data.data.message);
273+
$scope.errorMessage = response.data.data.message;
274+
$uibModal.open({
275+
animation: true,
276+
scope: $scope,
277+
templateUrl: 'app/pages/workflows/modals/errorModal.html',
278+
size: 'md',
279+
});
280+
return true;
281+
}
282+
}, function errorCallback(response) {
283+
console.log("Error occurred during getWorkflows");
284+
console.log("Response:" + response);
285+
if (response.statusText) {
286+
$scope.errorMessage = response.statusText;
287+
} else {
288+
$scope.errorMessage = response;
289+
}
290+
$uibModal.open({
291+
animation: true,
292+
scope: $scope,
293+
templateUrl: 'app/pages/workflows/modals/errorModal.html',
294+
size: 'md',
295+
});
296+
return true;
297+
});
298+
}
299+
300+
function undeployWorkflow(index, password) {
301+
var req;
302+
303+
console.log('undeploying workflow ' + $scope.workflows[index].id);
304+
$scope.currentWorkflow = $scope.workflows[index].name;
305+
console.log($scope.currentWorkflow);
306+
if (!$scope.workflowUndeploymentModal) {
307+
$scope.workflowUndeploymentModal = $uibModal.open({
308+
animation: true,
309+
scope: $scope,
310+
backdrop : 'static',
311+
keyboard : false,
312+
templateUrl: 'app/pages/profile/modals/workflowUndeploymentModal.html',
313+
size: 'sm',
314+
});
315+
}
316+
$scope.workflows[index].status='undeploying';
317+
req = {
318+
method: 'POST',
319+
url: urlPath,
320+
headers: {
321+
'Content-Type': 'application/json'
322+
},
323+
data: JSON.stringify({ "action" : "undeployWorkflow", "data" : { "user" : { "token" : token } , "workflow" : { "id" : $scope.workflows[index].id } } })
324+
}
325+
326+
$http(req).then(function successCallback(response) {
327+
328+
if (response.data.status=="success") {
329+
setTimeout(function() {$scope.workflows[index].status='undeployed'; checkDeployedWorkflows(password); }, 2000);
330+
331+
} else {
332+
console.log("Failure status returned by undeployWorkflow");
333+
console.log("Message:" + response.data.data.message);
334+
$scope.workflowUndeploymentModal.dismiss();
335+
$scope.errorMessage = response.data.data.message;
336+
$uibModal.open({
337+
animation: true,
338+
scope: $scope,
339+
templateUrl: 'app/pages/workflows/modals/errorModal.html',
340+
size: 'md',
341+
});
342+
}
343+
}, function errorCallback(response) {
344+
console.log("Error occurred during undeployWorkflow");
345+
console.log("Response:" + response);
346+
$scope.workflowUndeploymentModal.dismiss();
347+
if (response.statusText) {
348+
$scope.errorMessage = response.statusText;
349+
} else {
350+
$scope.errorMessage = response;
351+
}
352+
353+
$uibModal.open({
354+
animation: true,
355+
scope: $scope,
356+
templateUrl: 'app/pages/workflows/modals/errorModal.html',
357+
size: 'md',
358+
});
359+
360+
});
361+
159362
}
160363

161364
function changePassword(password, newPassword) {
@@ -166,7 +369,9 @@
166369
headers: {
167370
'Content-Type': 'application/json'
168371
},
372+
169373
data: JSON.stringify({ "action" : "changePassword", "data" : { "user" : { "email" : $scope.email, "password" : password, "new_password" : newPassword } } })
374+
170375
}
171376

172377
$http(req).then(function successCallback(response) {
@@ -184,7 +389,6 @@
184389
templateUrl: 'app/pages/workflows/modals/errorModal.html',
185390
size: 'md',
186391
});
187-
188392
}
189393
}, function errorCallback(response) {
190394
console.log("Error occurred during changePassword request");
@@ -200,7 +404,6 @@
200404
templateUrl: 'app/pages/workflows/modals/errorModal.html',
201405
size: 'md',
202406
});
203-
204407
});
205408
}
206409
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<!--
2+
Copyright 2020 The KNIX Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
17+
18+
<div class="modal-content">
19+
<div class="modal-header bg-danger">
20+
<i class="ion-flame modal-icon"></i><span>Delete Account</span>
21+
</div>
22+
<div class="modal-body text-center">
23+
Permanently delete all user code and object store data associated with this account?
24+
</div>
25+
<div class="modal-footer">
26+
<button type="button" class="btn btn-primary" ng-click="undeployAllWorkflows();$dismiss();">Yes</button> <button type="button" class="btn btn-danger" ng-click="clearPassword();$dismiss()">No</button>
27+
</div>
28+
</div>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<!--
2+
Copyright 2020 The KNIX Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
<div class="modal-content">
17+
<div class="modal-body text-center">
18+
<br>
19+
<span style="font-size:16px">Please wait</span>
20+
<br><br>
21+
<span style="font-size:14px">Undeploying {{ currentWorkflow }} workflow</span>
22+
<br><br>
23+
<img style="display: inline;margin:0px;" height="auto" src="assets/img/preloader-dots.gif">
24+
<br>
25+
</div>
26+
</div>

0 commit comments

Comments
 (0)