guide default admin pattern - wwwsolutions/nestjs-starter-kit GitHub Wiki
Example from Prisma-GraphQL integration
This is a common pattern. Upon initialization application loads default admin from environment and saves it into database.
# apps/api/.env.development
##### ADMIN CONFIGURATION ################################################################################
### REQUIRED
ADMIN_EMAIL='[email protected]'
ADMIN_PASSWORD='password'
# libs/api/config/features/src/lib/validation.schema.ts
/* --------------------------------------------------------------
ADMIN
api/config/features/src/lib/configs/admin.configuration.ts
--------------------------------------------------------------- */
// REQUIRED
ADMIN_EMAIL: Joi.string()
.email()
.required()
.description('API default admin email'),
ADMIN_PASSWORD: Joi.string()
.required()
.description('API default admin password'),
// libs/api/config/features/src/lib/configs/admin.configuration.ts
import { Inject } from '@nestjs/common';
import { ConfigType, registerAs } from '@nestjs/config';
import { AuthenticationUtils } from '@wwwsolutions/shared/utils';
import { UserCreateInput } from '@wwwsolutions/api/data-access/models';
export const adminConfiguration = registerAs('admin', async () => ({
admin: {
email: process.env.ADMIN_EMAIL as string,
password: await AuthenticationUtils.hash(
process.env.ADMIN_PASSWORD as string
),
get defaultAdmin(): UserCreateInput {
return {
email: this.email,
password: this.password,
};
},
},
}));
export type AdminConfiguration = ConfigType<typeof adminConfiguration>;
export const InjectAdminConfig = () => Inject(adminConfiguration.KEY);
// libs/api/config/features/src/lib/registrations/business-logic-configs.registration.ts
import { adminConfiguration } from '../configs/admin.configuration';
export const businessLogicConfigs: any = [adminConfiguration];
// libs/api/config/features/src/index.ts
export * from './lib/configs/admin.configuration';
// libs/api/data-access/core/src/lib/prisma-data.service.ts
...
import {
InjectAdminConfig,
AdminConfiguration,
} from '@wwwsolutions/api/config/features';
...
@Injectable()
export class PrismaDataService
extends PrismaClient
implements OnModuleInit, OnModuleDestroy
{
...
private readonly defaultAdmin: UserCreateInput | undefined;
...
constructor(
...
@InjectAdminConfig()
private readonly adminConfiguration: AdminConfiguration
...
) {
...
this.defaultAdmin = this.adminConfiguration.admin.defaultAdmin;
this.logger.log(
`🔶 Load default admin user from .env via adminConfiguration, '${this.defaultAdmin.email}'`
);
...
}
}
// libs/api/data-access/core/src/lib/prisma-data.service.ts
@Injectable()
export class PrismaDataService
extends PrismaClient
implements OnModuleInit, OnModuleDestroy
{
...
async onModuleInit(): Promise<void> {
...
await this.ensureDefaultAdminUser();
}
...
...
// [HELPER METHODS]
/**
* Ensures that default admin user exists in database,
* if not, it creates one from from data stored in .env
*/
private async ensureDefaultAdminUser(): Promise<boolean> {
// Check if default admin user exists in database
const found = await this.findUserByEmail(this.defaultAdmin!.email);
if (found) {
this.logger.log(`🤓 Existing default admin user: '${found.email}'`);
return true;
}
// Default admin user does not exist in database, create it
const created = await this.createUser({
data: this.defaultAdmin!,
});
this.logger.log(`🤓 Created default admin user: '${created.email}'`);
return true;
}
...
}