Completed
Pull Request — master (#2472)
by Kevin
23:34 queued 05:01
created

html/inc/delete_account.inc::is_over_but_not_validated()   B

Complexity

Conditions 5
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 4
Ratio 57.14 %

Importance

Changes 0
Metric Value
cc 5
eloc 5
nc 2
nop 1
dl 4
loc 7
rs 8.8571
c 0
b 0
f 0
1
<?php
2
// This file is part of BOINC.
3
// https://boinc.berkeley.edu
4
// Copyright (C) 2018 University of California
5
//
6
// BOINC is free software; you can redistribute it and/or modify it
7
// under the terms of the GNU Lesser General Public License
8
// as published by the Free Software Foundation,
9
// either version 3 of the License, or (at your option) any later version.
10
//
11
// BOINC is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
// See the GNU Lesser General Public License for more details.
15
//
16
// You should have received a copy of the GNU Lesser General Public License
17
// along with BOINC.  If not, see <https://www.gnu.org/licenses/>.
18
19
require_once("../inc/common_defs.inc");
20
require_once("../inc/util.inc");
21
require_once("../inc/user.inc");
22
require_once("../inc/host.inc");
23
require_once("../inc/friend.inc");
24
require_once("../inc/boinc_db.inc");
25
require_once("../inc/submit_util.inc");
26
require_once("../project/project.inc");
27
28
// Constants for different methods of deleting accounts
29
// These correspond to the value used in the config.xml 
30
// field of <enable_delete_account/>
31
define("DELETE_ACCOUNT_METHOD_OBFUSCATE", 1);
32
define("DELETE_ACCOUNT_METHOD_WIPE", 2);
33
define("DELETE_ACCOUNT_METHOD_PROJECT_DEFINED", 3);
34
35
// Constant for how long to sleep after invalidating authenticator before proceeding with rest of delete
36
// This is done on the chance that there is an active scheduler request in progress  
37
if (!defined("DELETE_DELAY")) define("DELETE_DELAY", 2);
38
39
40
function check_delete_account_token($userid, $token) {
41
    if( !is_valid_token($userid, $token, TOKEN_TYPE_DELETE_ACCOUNT) ) {
42
        sleep(LOGIN_FAIL_SLEEP_SEC);
43
        return false;
44
    }
45
    return true;
46
}
47
48
/*
49
* This function saves the minimal information from the user and their hosts
50
* so that db_dump can provide the information necessary to export the deleted_user
51
* and deleted_host files.  These records are deleted after 60 days by the 
52
* daily ops task "delete_expired_users_and_hosts.php"
53
*/
54
function insert_deleted_records($user) {
55
    BoincUserDeleted::insert_user($user);
56
    BoincHostDeleted::insert_hosts_for_user($user);
57
}
58
59
/*
60
* This method selects which delete method to utilize.  Projects can implement their own method
61
* and make that a third mechanism if they have a need to
62
*/
63
function delete_account($user) {
64
    $config = get_config();
65
    $enable_delete_account = parse_config($config, "<enable_delete_account>");
66
    if ( $enable_delete_account == DELETE_ACCOUNT_METHOD_OBFUSCATE ) {
67
        return obfuscate_account($user);
68
    } else if ( $enable_delete_account == DELETE_ACCOUNT_METHOD_WIPE ) {
69
        return wipe_account($user);
70
    } else if ( $enable_delete_account == DELETE_ACCOUNT_METHOD_PROJECT_DEFINED ) {
71
        return project_delete_account($user);
72
    } 
73
    return false;
74
}
75
76
// This method invalidates the authenticator and then sleeps for
77
// DELETE_DELAY seconds in order to let any active scheduler requests complete.
78
function invalidate_authenticator($user) {
79
    $x = "deleted_".time()."_".random_string();
80
    $retval = $user->update("authenticator='$x'");
81
    if (!$retval) return false;
82
    sleep(DELETE_DELAY);
83
    return true;
84
}
85
86
// "obfuscate" an account: leave user record (for DB consistency) but:
87
//  - set email address and authenticator to "deleted_time_randomstring"
88
//  - clear name, country, postal_code
89
//  - remove from team
90
//  - delete posts, subscriptions, and forum prefs
91
//  - delete private messages (sent and received)
92
//  - delete profile and associated image
93
// for each host:
94
//  - clear domain_name, last_ip_addr
95
//
96
function obfuscate_account($user) {
97
    $retval = invalidate_authenticator($user);
98
    if (!$retval) return false;
99
    insert_deleted_records($user);
100
    $x = "deleted_".time()."_".random_string();
101
    $retval = $user->update("email_addr='$x', authenticator='$x', name='deleted', country='', postal_code='', has_profile=0");
102
    if (!$retval) return false;
103
    user_quit_team($user);
104
    forum_delete_user($user);
105
    pm_delete_user($user);
106
    anonymize_hosts($user);
107
    delete_profile($user);
108
    delete_friends($user);
109
    return true;
110
}
111
112
113
// return true if the result is in progress
114
function is_in_progress($res) {
115
    if ($res->server_state == RESULT_SERVER_STATE_IN_PROGRESS) {
116
        return true;
117
    }
118
    return false;
119
}
120
121
// returns true if the result finished successfully but is either 
122
// pending validation or inconclusive
123
function is_over_but_not_validated($res) {
124 View Code Duplication
    if ($res->server_state == RESULT_SERVER_STATE_OVER && $res->outcome == RESULT_OUTCOME_SUCCESS &&
125
            ($res->validate_state == VALIDATE_STATE_INIT || $res->validate_state == VALIDATE_STATE_INCONCLUSIVE) ) {
126
        return true;
127
    }    
128
    return false;
129
}
130
131
function transition_workunit($res) {
132
    $now = time();
133
    BoincWorkunit::update_aux("transition_time=$now where id=$res->workunitid");
134
}
135
136
// This method handles dissassociating the user from their results.
137
// It will cancel all in progress or returned, but not yet validated 
138
// results for a user.  For other results, it will set the userid and 
139
// hostid fields to 0
140
function cancel_results_for_user($user) {
141
    $ress = BoincResult::enum("userid = $user->id");
142
    $cancel_clause="server_state=".RESULT_SERVER_STATE_OVER.", outcome=".RESULT_OUTCOME_CLIENT_DETACHED.", validate_state=".VALIDATE_STATE_INVALID;
143
    $set_id_clause="hostid=0, userid=0";
144
    foreach($ress as $res) {
145
        if (is_in_progress($res) || is_over_but_not_validated($res)) {
146
            $res->update($cancel_clause.", ".$set_id_clause);
147
            transition_workunit($res);
148
        } else {
149
            $res->update($set_id_clause);
150
        }
151
    }
152
}
153
154
// This method deletes all rows from the database associated with the user
155
function wipe_account($user) {
156
    $retval = invalidate_authenticator($user);
157
    if (!$retval) return false;
158
159
    //insert records into tables for db_dump to announce deletion of user
160
    insert_deleted_records($user);
161
162
    // delete remote submit user
163
    delete_remote_submit_user($user);  // from submit_util.inc
164
    
165
    // remove user's team records
166
    user_erase_team_owner($user);      // from team.inc
167
    user_quit_team($user);        // from team.inc
168
    user_erase_team_delta($user); // from team.inc
169
    
170
    // Items that do not have logic elsewhere
171
    // and do not have objects in boinc_db.inc
172
    $db = BoincDb::get();
173
    if (!$db) die("no DB connection");
174
    $db->do_query("delete from credited_job where userid = $user->id");
175
    $db->do_query("delete from donation_paypal where userid = $user->id");
176
    $db->do_query("delete from banishment_vote where userid = $user->id");
177
    $db->do_query("delete from post_ratings where post in ( select id from post where user = $user->id )");
178
    $db->do_query("delete from post_ratings where user = $user->id");
179
    $db->do_query("delete from msg_from_host where hostid in (select id from host where userid = $user->id )");
180
    $db->do_query("delete from msg_to_host where hostid in (select id from host where userid = $user->id )");
181
    $db->do_query("delete from sent_email where userid = $user->id");
182
    
183
    
184
    //It is much faster to update results with single query
185
    cancel_results_for_user($user);
186
    
187
    BoincHostAppVersion::delete_for_user($user->id);
188
    BoincHost::delete_for_user($user->id);
189
190
    // final action
191
    delete_user($user);  //from user_util.inc
192
    return true;
193
}
194