1- const fs = require ( 'fs' )
1+ const fs = require ( 'fs-extra ' )
22const Handlebars = require ( 'handlebars' )
33const path = require ( 'path' )
44const { URL } = require ( 'url' )
@@ -8,6 +8,7 @@ const { loadConfig } = require('./common')
88const { isValidUsername } = require ( '../../lib/common/user-utils' )
99const blacklistService = require ( '../../lib/services/blacklist-service' )
1010const { initConfigDir, initTemplateDirs } = require ( '../../lib/server-config' )
11+ const { fromServerConfig } = require ( '../../lib/models/oidc-manager' )
1112
1213const AccountManager = require ( '../../lib/models/account-manager' )
1314const EmailService = require ( '../../lib/services/email-service' )
@@ -30,15 +31,71 @@ module.exports = function (program) {
3031 }
3132
3233 const invalidUsernames = await getInvalidUsernames ( config )
34+ const host = SolidHost . from ( { port : config . port , serverUri : config . serverUri } )
35+ const accountManager = getAccountManager ( config , host )
3336
3437 if ( options . notify ) {
35- return notifyUsers ( invalidUsernames , config )
38+ return notifyUsers ( invalidUsernames , accountManager , config )
39+ }
40+
41+ if ( options . delete ) {
42+ return deleteUsers ( invalidUsernames , accountManager , config , host )
3643 }
3744
3845 listUsernames ( listUsernames )
3946 } )
4047}
4148
49+ async function createNewIndexFile ( username , accountManager , invalidUsernameTemplate , dateOfRemoval , supportEmail , fileOptions ) {
50+ const userDirectory = accountManager . accountDirFor ( username )
51+ const currentIndex = path . join ( userDirectory , 'index.html' )
52+ const currentIndexExists = await fileExists ( currentIndex )
53+ const backupIndex = path . join ( userDirectory , 'index.backup.html' )
54+ const backupIndexExists = await fileExists ( backupIndex )
55+ if ( currentIndexExists && ! backupIndexExists ) {
56+ await fileRename ( currentIndex , backupIndex )
57+ const newIndexSource = invalidUsernameTemplate ( {
58+ username,
59+ dateOfRemoval,
60+ supportEmail
61+ } )
62+ fs . writeFileSync ( currentIndex , newIndexSource , fileOptions )
63+ console . info ( `index.html updated for user ${ username } ` )
64+ }
65+ }
66+
67+ async function deleteUsers ( usernames , accountManager , config , host ) {
68+ const oidcManager = fromServerConfig ( {
69+ ...config ,
70+ host
71+ } )
72+ const deletingUsers = usernames
73+ . map ( async username => {
74+ try {
75+ const user = accountManager . userAccountFrom ( { username } )
76+ await oidcManager . users . deleteUser ( user )
77+ } catch ( error ) {
78+ if ( error . message !== 'No email given' ) {
79+ // 'No email given' is an expected error that we want to ignore
80+ throw error
81+ }
82+ }
83+ const userDirectory = accountManager . accountDirFor ( username )
84+ await fs . remove ( userDirectory )
85+ } )
86+ await Promise . all ( deletingUsers )
87+ console . info ( `Deleted ${ deletingUsers . length } users succeeded` )
88+ }
89+
90+ function getAccountManager ( config , host ) {
91+ const ldp = new LDP ( config )
92+ return AccountManager . from ( {
93+ host,
94+ store : ldp ,
95+ multiuser : config . multiuser
96+ } )
97+ }
98+
4299async function getInvalidUsernames ( config ) {
43100 const files = await util . promisify ( fs . readdir ) ( config . root )
44101 const hostname = new URL ( config . serverUri ) . hostname
@@ -56,14 +113,7 @@ function listUsernames (usernames) {
56113 console . info ( `${ usernames . length } invalid usernames were found:${ usernames . map ( username => `\n- ${ username } ` ) } ` )
57114}
58115
59- async function notifyUsers ( usernames , config ) {
60- const ldp = new LDP ( config )
61- const host = SolidHost . from ( { port : config . port , serverUri : config . serverUri } )
62- const accountManager = AccountManager . from ( {
63- host,
64- store : ldp ,
65- multiuser : config . multiuser
66- } )
116+ async function notifyUsers ( usernames , accountManager , config ) {
67117 const twoWeeksFromNow = Date . now ( ) + 14 * 24 * 60 * 60 * 1000
68118 const dateOfRemoval = ( new Date ( twoWeeksFromNow ) ) . toLocaleDateString ( )
69119 const { supportEmail } = config
@@ -72,35 +122,6 @@ async function notifyUsers (usernames, config) {
72122 await sendEmails ( config , usernames , accountManager , dateOfRemoval , supportEmail )
73123}
74124
75- async function updateIndexFiles ( usernames , accountManager , dateOfRemoval , supportEmail ) {
76- const invalidUsernameFilePath = path . join ( process . cwd ( ) , 'default-views/account/invalid-username.hbs' )
77- const fileOptions = {
78- encoding : 'utf-8'
79- }
80- const source = fs . readFileSync ( invalidUsernameFilePath , fileOptions )
81- const invalidUsernameTemplate = Handlebars . compile ( source )
82- const updatingFiles = usernames . map ( username => createNewIndex ( username , accountManager , invalidUsernameTemplate , dateOfRemoval , supportEmail , fileOptions ) )
83- return Promise . all ( updatingFiles )
84- }
85-
86- async function createNewIndex ( username , accountManager , invalidUsernameTemplate , dateOfRemoval , supportEmail , fileOptions ) {
87- const userDirectory = accountManager . accountDirFor ( username )
88- const currentIndex = path . join ( userDirectory , 'index.html' )
89- const currentIndexExists = await fileExists ( currentIndex )
90- const backupIndex = path . join ( userDirectory , 'index.backup.html' )
91- const backupIndexExists = await fileExists ( backupIndex )
92- if ( currentIndexExists && ! backupIndexExists ) {
93- await fileRename ( currentIndex , backupIndex )
94- const newIndexSource = invalidUsernameTemplate ( {
95- username,
96- dateOfRemoval,
97- supportEmail
98- } )
99- fs . writeFileSync ( currentIndex , newIndexSource , fileOptions )
100- console . info ( `index.html updated for user ${ username } ` )
101- }
102- }
103-
104125async function sendEmails ( config , usernames , accountManager , dateOfRemoval , supportEmail ) {
105126 if ( config . email && config . email . host ) {
106127 const configPath = initConfigDir ( config )
@@ -126,3 +147,14 @@ async function sendEmails (config, usernames, accountManager, dateOfRemoval, sup
126147 console . info ( 'You have not configured an email service.' )
127148 console . info ( 'Please set it up to send users email about their accounts' )
128149}
150+
151+ async function updateIndexFiles ( usernames , accountManager , dateOfRemoval , supportEmail ) {
152+ const invalidUsernameFilePath = path . join ( process . cwd ( ) , 'default-views/account/invalid-username.hbs' )
153+ const fileOptions = {
154+ encoding : 'utf-8'
155+ }
156+ const source = fs . readFileSync ( invalidUsernameFilePath , fileOptions )
157+ const invalidUsernameTemplate = Handlebars . compile ( source )
158+ const updatingFiles = usernames . map ( username => createNewIndexFile ( username , accountManager , invalidUsernameTemplate , dateOfRemoval , supportEmail , fileOptions ) )
159+ return Promise . all ( updatingFiles )
160+ }
0 commit comments