Skip to content

Commit

Permalink
Merge branch 'release/4.0.6'
Browse files Browse the repository at this point in the history
  • Loading branch information
brunobuddy committed Nov 15, 2024
2 parents 78bfc72 + f2b2ed5 commit 3971c6f
Show file tree
Hide file tree
Showing 39 changed files with 766 additions and 92 deletions.
1 change: 1 addition & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
Check the NPM packages that require a new publication or release:

- [ ] [manifest](https://www.npmjs.com/package/manifest)
- [] [add-manifest](https://www.npmjs.com/package/add-manifest)
- [ ] [@mnfst/sdk](https://www.npmjs.com/package/@mnfst/sdk)

## Check list before submitting
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</p>

<p align='center'>
<strong>A backend so simple that it fits in a YAML file</strong>
<strong>A backend so simple that it fits into 1 YAML file</strong>
<br><br>
<a href="https://www.npmjs.com/package/manifest" target="_blank"><img alt="npm" src="https://img.shields.io/npm/v/manifest"></a>
<a href="https://www.codefactor.io/repository/github/mnfst/manifest" target="_blank"><img alt="CodeFactor Grade" src="https://img.shields.io/codefactor/grade/github/mnfst/manifest"></a>
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion packages/add-manifest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ npm install
# Run from a test folder to prevent messing with project files.
mkdir test-folder
cd test-folder
../bin/dev.js create
../bin/dev.js
```

However due to the monorepo workspace structure, the launch script will fail as the path to the node modules folder is different than when served.

## Publish

```bash
Expand Down
58 changes: 58 additions & 0 deletions packages/add-manifest/assets/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<br>
<p align="center">
<a href="https://manifest.build/#gh-light-mode-only">
<img alt="manifest" src="https://manifest.build/assets/images/logo-transparent.svg" height="55px" alt="Manifest logo" title="Manifest - A backend so simple that it fits in a YAML file" />
</a>
<a href="https://manifest.build/#gh-dark-mode-only">
<img alt="manifest" src="https://manifest.build/assets/images/logo-light.svg" height="55px" alt="Manifest logo" title="Manifest - A backend so simple that it fits in a YAML file" />
</a>
</p>

<p align='center'>
<strong>A backend so simple that it fits into 1 YAML file</strong>
<br><br>
<a href="https://www.npmjs.com/package/manifest" target="_blank"><img alt="npm" src="https://img.shields.io/npm/v/manifest"></a>
<a href="https://www.codefactor.io/repository/github/mnfst/manifest" target="_blank"><img alt="CodeFactor Grade" src="https://img.shields.io/codefactor/grade/github/mnfst/manifest"></a>
<a href="https://discord.com/invite/FepAked3W7" target="_blank"><img alt="Discord" src="https://img.shields.io/discord/1089907785178812499?label=discord"></a>
<a href="https://opencollective.com/mnfst" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
<a href="https://www.codetriage.com/mnfst/manifest" target="_blank"><img alt="CodeTriage" src="https://www.codetriage.com/mnfst/manifest/badges/users.svg"></a>
<a href="https://github.com/mnfst/manifest/blob/develop/LICENSE" target="_blank"><img alt="License MIT" src="https://img.shields.io/badge/licence-MIT-green"></a>
<br>
</p>

## Description

This project was made with [Manifest](https://github.com/mnfst/manifest).

## Installation

```bash
$ npm install
```

## Running the app

To run the app in the development mode:

```bash
npm run manifest
```

- Open [http://localhost:1111](http://localhost:1111) to open your admin UI it in your browser
- Open [http://localhost:1111/api](http://localhost:111/api) to view your REST API documentation

The page will reload when you make changes.

## Seed dummy data

Seeds some dummy data for your entities:

```bash
npm run manifest:seed
```

## Community & Resources

- [Docs](https://manifest.build/docs) - Get started with Manifest
- [Discord](https://discord.gg/FepAked3W7) - Come chat with the community
- [Github](https://github.com/mnfst/manifest/issues) - Report bugs and share ideas to improve the product.
2 changes: 1 addition & 1 deletion packages/add-manifest/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "add-manifest",
"version": "1.0.2",
"version": "1.0.3",
"author": "Manifest",
"description": "Add Manifest backend",
"homepage": "https://manifest.build",
Expand Down
43 changes: 32 additions & 11 deletions packages/add-manifest/src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ export class MyCommand extends Command {
* 5. Update the .vscode/settings.json file with the recommended settings.
* 6. Update the .gitignore file with the recommended settings.
* 7. Update the .env file with the environment variables.
* 8. Install the new packages.
* 9. Serve the new app.
* 10. Wait for the server to start.
* 11. Seed the database.
* 12. Open the browser.
* 8. If no README.md file exists, create one.
* 9. Install the new packages.
* 10. Serve the new app.
* 11. Wait for the server to start.
* 12. Seed the database.
* 13. Open the browser.
*/
async run(): Promise<void> {
const folderName = 'manifest'
Expand All @@ -42,6 +43,7 @@ export class MyCommand extends Command {

const spinner = ora('Add Manifest to your project...').start()

// * 1. Create a folder with the name `manifest`.
// Construct the folder path. This example creates the folder in the current working directory.
const folderPath = path.join(process.cwd(), folderName)

Expand All @@ -56,6 +58,7 @@ export class MyCommand extends Command {
// Create the folder
fs.mkdirSync(folderPath)

// * 2. Create a file inside the folder with the name `manifest.yml`.
// Path where the new file should be created
const newFilePath = path.join(folderPath, initialFileName)

Expand Down Expand Up @@ -91,7 +94,7 @@ export class MyCommand extends Command {
updatePackageJsonFile({
fileContent: packageJson,
newPackages: {
manifest: '^4.0.4'
manifest: '^4.0.5'
},
newScripts: {
manifest: 'node node_modules/manifest/scripts/watch/watch.js',
Expand Down Expand Up @@ -155,22 +158,40 @@ export class MyCommand extends Command {
})
)

// Update the .gitignore file with the recommended settings.
// * 7. Update the .env file with the environment variables.
const gitignorePath = path.join(process.cwd(), '.gitignore')
let gitignoreContent = ''

if (fs.existsSync(gitignorePath)) {
gitignoreContent = fs.readFileSync(gitignorePath, 'utf8')
}

if (!gitignoreContent.includes('node_modules')) {
gitignoreContent += '\nnode_modules'
gitignoreContent += '\n.env'
}
const newGitignoreLines: string[] = [
'node_modules',
'.env',
'public',
'manifest/backend.db'
]
newGitignoreLines.forEach((line) => {
if (!gitignoreContent.includes(line)) {
gitignoreContent += `\n${line}`
}
})

fs.writeFileSync(gitignorePath, gitignoreContent)

spinner.succeed()

// * 8. Add a README.md file if it doesn't exist.
const readmeFilePath = path.join(process.cwd(), 'README.md')
if (!fs.existsSync(readmeFilePath)) {
fs.writeFileSync(
readmeFilePath,
fs.readFileSync(path.join(assetFolderPath, 'README.md'), 'utf8')
)
}

// * 9. Install the new packages.
spinner.start('Install dependencies...')

// Install deps.
Expand Down
5 changes: 2 additions & 3 deletions packages/core/admin/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
<ng-container *ngIf="!isLogin">
<app-touch-menu class="is-hidden-desktop"></app-touch-menu>

<app-touch-menu class="is-hidden-desktop"></app-touch-menu>
</ng-container>

<app-flash-message></app-flash-message>

<div class="wrapper" >
<div class="wrapper">
<div class="columns">
<aside class="column aside menu px-0 is-hidden-touch" *ngIf="!isLogin">
<app-side-menu></app-side-menu>
Expand Down
9 changes: 7 additions & 2 deletions packages/core/admin/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,18 @@ export class AppComponent implements OnInit {
currentUser: Admin
isLogin = true

constructor(private authService: AuthService, private router: Router) {}
constructor(
private authService: AuthService,
private router: Router
) {}

ngOnInit() {
this.router.events.subscribe((routeChanged) => {
if (routeChanged instanceof NavigationEnd) {
window.scrollTo(0, 0)
this.isLogin = routeChanged.url.includes('/auth/login')
this.isLogin =
routeChanged.url.includes('/auth/login') ||
routeChanged.url.includes('/auth/welcome')

if (this.isLogin) {
this.currentUser = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { RouterModule, Routes } from '@angular/router'
import { NotLoggedInGuard } from './guards/not-logged-in.guard'
import { LoginComponent } from './views/login/login.component'
import { LogoutComponent } from './views/logout/logout.component'
import { RegisterFirstAdminComponent } from './views/register-first-admin/register-first-admin.component'
import { IsDbEmptyGuard } from './guards/is-db-empty.guard'

export const authRoutes: Routes = [
{
Expand All @@ -14,6 +16,11 @@ export const authRoutes: Routes = [
{
path: 'logout',
component: LogoutComponent
},
{
path: 'welcome',
component: RegisterFirstAdminComponent,
canActivate: [IsDbEmptyGuard]
}
]

Expand Down
3 changes: 2 additions & 1 deletion packages/core/admin/src/app/modules/auth/auth.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import { SharedModule } from '../shared/shared.module'
import { AuthRoutingModule } from './auth-routing.module'
import { LoginComponent } from './views/login/login.component'
import { LogoutComponent } from './views/logout/logout.component'
import { RegisterFirstAdminComponent } from './views/register-first-admin/register-first-admin.component'

@NgModule({
declarations: [LoginComponent, LogoutComponent],
declarations: [LoginComponent, LogoutComponent, RegisterFirstAdminComponent],
imports: [CommonModule, AuthRoutingModule, SharedModule]
})
export class AuthModule {}
44 changes: 44 additions & 0 deletions packages/core/admin/src/app/modules/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,37 @@ export class AuthService {
})
}

/**
* Signs up a new admin and logs them in.
*
* @param {Object} credentials - The credentials of the new admin
* @param {string} credentials.email - The email of the new admin
* @param {string} credentials.password - The password of the new admin
*
* @returns {Promise<string>} The token of the new admin
*/
async signup(credentials: {
email: string
password: string
}): Promise<string> {
return (
firstValueFrom(
this.http.post(
`${environment.apiBaseUrl}/auth/admins/signup`,
credentials
)
) as Promise<{
token: string
}>
).then((res: { token: string }) => {
const token = res?.token
if (token) {
localStorage.setItem(TOKEN_KEY, token)
}
return token
})
}

logout(): void {
delete this.currentUserPromise
localStorage.removeItem(TOKEN_KEY)
Expand Down Expand Up @@ -76,4 +107,17 @@ export class AuthService {
) as Promise<{ exists: boolean }>
).then((res) => res.exists)
}

/**
* Returns true if the database is empty (no items, even admins), false otherwise.
*
* @returns {Promise<boolean>} true if the database is empty, false otherwise
*/
async isDbEmpty(): Promise<boolean> {
return (
firstValueFrom(
this.http.get(`${environment.apiBaseUrl}/db/is-db-empty`)
) as Promise<{ empty: boolean }>
).then((res) => res.empty)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Injectable } from '@angular/core'
import { Router } from '@angular/router'
import { AuthService } from '../auth.service'

@Injectable({
providedIn: 'root'
})
export class IsDbEmptyGuard {
constructor(
private authService: AuthService,
private router: Router
) {}
async canActivate(): Promise<boolean> {
const isDbEmpty = await this.authService.isDbEmpty()

if (isDbEmpty) {
return true
}

this.router.navigate(['/auth/login'])
return false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'

export function confirmPasswordValidator(
passwordControlName: string
): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const formGroup = control.parent
if (!formGroup) return null

const passwordControl = formGroup.get(passwordControlName)
if (!passwordControl) return null

const password = passwordControl.value
const confirmPassword = control.value

if (!confirmPassword || password !== confirmPassword) {
return { confirmPasswordMismatch: true }
}

return null
}
}
Loading

0 comments on commit 3971c6f

Please sign in to comment.