forked from engineering/cloudservices
feat: usermod command
parent
b40b39ca12
commit
64a68e51a3
|
@ -39,6 +39,7 @@
|
||||||
"import/prefer-default-export": "off",
|
"import/prefer-default-export": "off",
|
||||||
"no-useless-constructor": "off",
|
"no-useless-constructor": "off",
|
||||||
"@typescript-eslint/no-useless-constructor": 2,
|
"@typescript-eslint/no-useless-constructor": 2,
|
||||||
"import/extensions": "off"
|
"import/extensions": "off",
|
||||||
|
"consistent-return": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,6 +4,8 @@ import { randomBytes } from 'crypto';
|
||||||
import { AccountInterface } from '../models';
|
import { AccountInterface } from '../models';
|
||||||
import { Client } from '..';
|
import { Client } from '..';
|
||||||
|
|
||||||
|
export const LINUX_USERNAME_REGEX = /^[a-z][-a-z0-9]*$/;
|
||||||
|
|
||||||
export default class AccountUtil {
|
export default class AccountUtil {
|
||||||
public client: Client;
|
public client: Client;
|
||||||
|
|
||||||
|
|
|
@ -311,16 +311,9 @@ export default class Util {
|
||||||
return Promise.resolve(log);
|
return Promise.resolve(log);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getAcctHash(userpath: string) {
|
|
||||||
try {
|
|
||||||
return fs.readFileSync(`${userpath}/.securesign/auth`).toString();
|
|
||||||
} catch (error) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public parseCertificate(pem: string) {
|
public parseCertificate(pem: string) {
|
||||||
return axios.post<Certificate>('https://certapi.libraryofcode.org/parse', pem);
|
return axios.post<Certificate>('https://certapi.libraryofcode.org/parse', pem)
|
||||||
|
.then((response) => response.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public upload(text: string, extension = 'txt') {
|
public upload(text: string, extension = 'txt') {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { GuildMember, Message } from 'discord.js';
|
import { GuildMember, Message } from 'discord.js';
|
||||||
import { Client, Command } from '../class';
|
import { Client, Command } from '../class';
|
||||||
|
import { LINUX_USERNAME_REGEX } from '../class/AccountUtil';
|
||||||
|
|
||||||
export default class CreateAccount extends Command {
|
export default class CreateAccount extends Command {
|
||||||
constructor(client: Client) {
|
constructor(client: Client) {
|
||||||
|
@ -32,7 +33,7 @@ export default class CreateAccount extends Command {
|
||||||
if (checkAccount) return this.error(message.channel, 'Account already exists with this username.');
|
if (checkAccount) return this.error(message.channel, 'Account already exists with this username.');
|
||||||
|
|
||||||
if (!this.client.util.isValidEmail(args[1])) return this.error(message.channel, 'Invalid email address supplied.');
|
if (!this.client.util.isValidEmail(args[1])) return this.error(message.channel, 'Invalid email address supplied.');
|
||||||
if (!/^[a-z][-a-z0-9]*$/.test(args[2])) return this.error(message.channel, 'Invalid username supplied.');
|
if (!LINUX_USERNAME_REGEX.test(args[2])) return this.error(message.channel, 'Invalid username supplied.');
|
||||||
|
|
||||||
const confirmation = await this.loading(message.channel, 'Creating account...');
|
const confirmation = await this.loading(message.channel, 'Creating account...');
|
||||||
const data = await this.client.util.accounts.createAccount({ userID: args[0], username: args[2], emailAddress: args[1] }, message.author.id);
|
const data = await this.client.util.accounts.createAccount({ userID: args[0], username: args[2], emailAddress: args[1] }, message.author.id);
|
||||||
|
|
|
@ -37,9 +37,9 @@ export default class CWG_Data extends Command {
|
||||||
embed.addField('Account ID', domain.account.userID, true);
|
embed.addField('Account ID', domain.account.userID, true);
|
||||||
embed.addField('Domain', domain.domain, true);
|
embed.addField('Domain', domain.domain, true);
|
||||||
embed.addField('Port', String(domain.port), true);
|
embed.addField('Port', String(domain.port), true);
|
||||||
embed.addField('Certificate Issuer', cert.data.issuer.organization[0], true);
|
embed.addField('Certificate Issuer', cert.issuer.organization[0], true);
|
||||||
embed.addField('Certificate Subject', cert.data.issuer.commonName, true);
|
embed.addField('Certificate Subject', cert.issuer.commonName, true);
|
||||||
embed.addField('Certificate Expiration Date', moment(cert.data.notAfter).format('dddd, MMMM Do YYYY, h:mm:ss A'), true);
|
embed.addField('Certificate Expiration Date', moment(cert.notAfter).format('dddd, MMMM Do YYYY, h:mm:ss A'), true);
|
||||||
embed.setFooter(this.client.user.username, this.client.user.avatarURL());
|
embed.setFooter(this.client.user.username, this.client.user.avatarURL());
|
||||||
embed.setTimestamp();
|
embed.setTimestamp();
|
||||||
return embed;
|
return embed;
|
||||||
|
|
|
@ -28,6 +28,7 @@ export { default as systemd } from './systemd';
|
||||||
export { default as tier } from './tier';
|
export { default as tier } from './tier';
|
||||||
export { default as unban } from './unban';
|
export { default as unban } from './unban';
|
||||||
export { default as unlock } from './unlock';
|
export { default as unlock } from './unlock';
|
||||||
|
export { default as usermod } from './usermod';
|
||||||
export { default as users } from './users';
|
export { default as users } from './users';
|
||||||
export { default as warn } from './warn';
|
export { default as warn } from './warn';
|
||||||
export { default as whois } from './whois';
|
export { default as whois } from './whois';
|
||||||
|
|
|
@ -12,7 +12,7 @@ export default class Lock extends Command {
|
||||||
this.usage = `${this.client.config.prefix}lock [User Name | User ID/Mention] <Time> [Reason]`;
|
this.usage = `${this.client.config.prefix}lock [User Name | User ID/Mention] <Time> [Reason]`;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async run(message: Message, args: string[]) { // eslint-disable-line
|
public async run(message: Message, args: string[]) {
|
||||||
try {
|
try {
|
||||||
if (!args.length) return this.client.commands.get('help').run(message, [this.name]);
|
if (!args.length) return this.client.commands.get('help').run(message, [this.name]);
|
||||||
const account = await this.client.db.Account.findOne({ $or: [{ username: args[0] }, { userID: args[0].replace(/[<@!>]/gi, '') }] });
|
const account = await this.client.db.Account.findOne({ $or: [{ username: args[0] }, { userID: args[0].replace(/[<@!>]/gi, '') }] });
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
import { Message } from 'discord.js';
|
||||||
|
import { Client, Command } from '../class';
|
||||||
|
import { LINUX_USERNAME_REGEX } from '../class/AccountUtil';
|
||||||
|
|
||||||
|
export default class Usermod extends Command {
|
||||||
|
constructor(client: Client) {
|
||||||
|
super(client);
|
||||||
|
this.name = 'usermod';
|
||||||
|
this.description = 'Modifies properties of a user\'s cloud account';
|
||||||
|
this.permissions = { roles: ['662163685439045632', '701454780828221450'] };
|
||||||
|
this.enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async run(message: Message, args: string[]) {
|
||||||
|
if (!args.length) return this.client.commands.get('help').run(message, [this.name]);
|
||||||
|
const [, property, value] = args;
|
||||||
|
|
||||||
|
const account = await this.client.db.Account.findOne({ $or: [{ username: args[0] }, { userID: args[0] }] });
|
||||||
|
if (!account) return this.error(message.channel, 'Cannot find user.');
|
||||||
|
|
||||||
|
switch (property) {
|
||||||
|
case 'email': {
|
||||||
|
if (value === account.emailAddress) return this.error(message.channel, 'The new email address cannot be the same as the old one.');
|
||||||
|
if (await this.client.db.Account.exists({ emailAddress: value })) return this.error(message.channel, 'An account with this email address already exists.');
|
||||||
|
if (!this.client.util.isValidEmail(value)) return this.error(message.channel, 'The supplied email address is invalid.');
|
||||||
|
|
||||||
|
const modifyingPropertyResponse = await this.loading(message.channel, `Modifying \`${property}\` of \`${account.username}\`'s account...`);
|
||||||
|
await this.client.commands.get('notify')
|
||||||
|
.run(message, [account.username, ...(`Your email address has been changed from ${account.emailAddress} to ${value}.`.split(' '))]);
|
||||||
|
await account.updateOne({ emailAddress: value });
|
||||||
|
|
||||||
|
modifyingPropertyResponse.delete();
|
||||||
|
this.success(message.channel, `Successfully updated \`${account.username}\`'s email address.`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'username': {
|
||||||
|
if (value === account.username) return this.error(message.channel, 'The username cannot be the same as the old one.');
|
||||||
|
if (await this.client.db.Account.exists({ username: value })) return this.error(message.channel, 'An account with this username already exists.');
|
||||||
|
|
||||||
|
if (!LINUX_USERNAME_REGEX.test(value)) return this.error(message.channel, 'Please supply a valid username.');
|
||||||
|
if (value === 'root') return this.error(message.channel, 'This username is unavailable.');
|
||||||
|
|
||||||
|
const modifyingPropertyResponse = await this.loading(message.channel, `Modifying \`${property}\` of \`${account.username}\`'s account...`);
|
||||||
|
try {
|
||||||
|
await this.client.commands.get('lock')
|
||||||
|
.run(message, [account.username, ...(`Changing your username from \`${account.username}\` to \`${value}\`. DN/C`.split(' '))]);
|
||||||
|
|
||||||
|
await this.client.util.exec(`usermod -l ${value} ${account.username}`);
|
||||||
|
await this.client.util.exec(`usermod -d /home/${value} ${account.username}`);
|
||||||
|
|
||||||
|
await account.updateOne({
|
||||||
|
username: value,
|
||||||
|
homepath: `/home/${value}`,
|
||||||
|
});
|
||||||
|
await this.client.commands.get('unlock')
|
||||||
|
.run(message, [value, ...(`Your username has been successfully changed. Remember to use \`ssh ${value}@cloud.libraryofcode.org\` when logging in.`)]);
|
||||||
|
} catch (error) {
|
||||||
|
await this.client.commands.get('unlock')
|
||||||
|
.run(message, [account.username, ...('Your username change was unsuccessful. Please contact a Technician for more details.')]);
|
||||||
|
this.error(message.channel, 'Failed to modify username.');
|
||||||
|
return this.client.util.handleError(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
modifyingPropertyResponse.delete();
|
||||||
|
this.success(message.channel, 'Successfully modified username.');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
this.error(message.channel, 'Please specify a valid option.');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue