signup wizard experiment. (#415)

* signup wizard experiment.

* better signon wizard page logos (shuffled)

* adding border shadow.

* remove duplicate logo.

* adding join mailing list button.

* make sure unnecessary admin user is removed from the database.

* updated fasten-sources to fix incorrectly merged epic brands. see https://github.com/fastenhealth/fasten-onprem/issues/366
This commit is contained in:
Jason Kulatunga 2024-02-12 17:56:53 -08:00 committed by GitHub
parent d450f8b4e4
commit ea16305442
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 290 additions and 13 deletions

View File

@ -50,6 +50,11 @@ func (gr *GormRepository) CreateUser(ctx context.Context, user *models.User) err
return record.Error
}
//SECURITY:
//TODO: we should disallow reserved usernames:
// https://github.com/forwardemail/reserved-email-addresses-list/blob/master/admin-list.json
// https://github.com/shouldbee/reserved-usernames/blob/master/reserved-usernames.txt
//create user settings
err := gr.PopulateDefaultUserSettings(ctx, user.ID)
if err != nil {

View File

@ -8,6 +8,7 @@ import (
_0240114092806 "github.com/fastenhealth/fasten-onprem/backend/pkg/database/migrations/20240114092806"
_20240114103850 "github.com/fastenhealth/fasten-onprem/backend/pkg/database/migrations/20240114103850"
_20240208112210 "github.com/fastenhealth/fasten-onprem/backend/pkg/database/migrations/20240208112210"
"github.com/fastenhealth/fasten-onprem/backend/pkg/models"
databaseModel "github.com/fastenhealth/fasten-onprem/backend/pkg/models/database"
sourceCatalog "github.com/fastenhealth/fasten-sources/catalog"
sourcePkg "github.com/fastenhealth/fasten-sources/pkg"
@ -181,6 +182,18 @@ func (gr *GormRepository) Migrate() error {
return nil
},
},
{
ID: "20240212142126", // remove unnecessary admin user if present.
Migrate: func(tx *gorm.DB) error {
deleteResp := tx.Delete(&models.User{}, "username = ?", "admin")
if deleteResp.Error != nil {
tx.Logger.Error(context.Background(), fmt.Sprintf("An error occurred while removing placeholder admin user: %v", deleteResp.Error))
return deleteResp.Error
}
return nil
},
},
})
// run when database is empty

View File

@ -4,7 +4,6 @@ import (
"fmt"
"github.com/fastenhealth/fasten-onprem/backend/pkg/config"
"github.com/fastenhealth/fasten-onprem/backend/pkg/event_bus"
"github.com/fastenhealth/fasten-onprem/backend/pkg/models"
"github.com/sirupsen/logrus"
"net/url"
"strings"
@ -104,15 +103,6 @@ func newSqliteRepository(appConfig config.Interface, globalLogger logrus.FieldLo
return nil, err
}
// create/update admin user
//TODO: determine if this admin user is ncessary
//SECURITY: validate this user is necessary
adminUser := models.User{}
err = database.FirstOrCreate(&adminUser, models.User{Username: "admin"}).Error
if err != nil {
return nil, fmt.Errorf("Failed to create admin user! - %v", err)
}
//fail any Locked jobs. This is necessary because the job may have been locked by a process that was killed.
err = fastenRepo.CancelAllLockedBackgroundJobsAndFail()
if err != nil {

View File

@ -17,9 +17,12 @@ import {ExploreComponent} from './pages/explore/explore.component';
import {environment} from '../environments/environment';
import {DesktopCallbackComponent} from './pages/desktop-callback/desktop-callback.component';
import {BackgroundJobsComponent} from './pages/background-jobs/background-jobs.component';
import {AuthSignupWizardComponent} from './pages/auth-signup-wizard/auth-signup-wizard.component';
const routes: Routes = [
{ path: 'auth/signup/wizard', component: AuthSignupWizardComponent },
{ path: 'auth/signin', component: AuthSigninComponent },
{ path: 'auth/signin/callback/:idp_type', component: AuthSigninComponent },
{ path: 'auth/signup', component: AuthSignupComponent },

View File

@ -40,6 +40,7 @@ import { DesktopCallbackComponent } from './pages/desktop-callback/desktop-callb
import { BackgroundJobsComponent } from './pages/background-jobs/background-jobs.component';
import {FhirCardModule} from './components/fhir-card/fhir-card.module';
import {FhirDatatableModule} from './components/fhir-datatable/fhir-datatable.module';
import { AuthSignupWizardComponent } from './pages/auth-signup-wizard/auth-signup-wizard.component';
@NgModule({
declarations: [
@ -59,6 +60,7 @@ import {FhirDatatableModule} from './components/fhir-datatable/fhir-datatable.mo
ExploreComponent,
DesktopCallbackComponent,
BackgroundJobsComponent,
AuthSignupWizardComponent,
],
imports: [
FormsModule,

View File

@ -0,0 +1,104 @@
<div style="overflow:hidden;height: 95vh;" class="row">
<div *ngFor="let img of gridImages" class="col-1 nopadding">
<div class="d-flex h-100">
<div class="mx-auto my-auto">
<img src="assets/sources/{{img}}" class="rounded img-fluid opacity-20">
</div>
</div>
</div>
</div>
<div class="outer-div">
<div class="inner-div">
<div class="az-signin-wrapper">
<div class="az-card-signin" [ngStyle]="{'height': '560px' }">
<h1 class="az-logo">fasten</h1>
<div class="az-signin-header">
<h2>Let's Get Started!</h2>
<p>Create your Fasten Health administrator account</p>
<form #userForm="ngForm">
<div class="form-group">
<input name="full_name" required minlength="2" type="text" class="form-control" placeholder="Name">
<!-- <div *ngIf="full_name.invalid && (full_name.dirty || full_name.touched)" class="alert alert-danger">-->
<!-- <div *ngIf="full_name.errors?.['required']">-->
<!-- Name is required.-->
<!-- </div>-->
<!-- <div *ngIf="full_name.errors?.['minlength']">-->
<!-- Name must be at least 2 characters long.-->
<!-- </div>-->
<!-- </div>-->
</div><!-- form-group -->
<div class="form-group">
<input name="username" required autocapitalize="none" minlength="2" type="text" class="form-control" placeholder="Username">
<!-- <div *ngIf="username.invalid && (username.dirty || username.touched)" class="alert alert-danger">-->
<!-- <div *ngIf="username.errors?.['required']">-->
<!-- Username is required.-->
<!-- </div>-->
<!-- <div *ngIf="username.errors?.['minlength']">-->
<!-- Username must be at least 4 characters long.-->
<!-- </div>-->
<!-- </div>-->
</div><!-- form-group -->
<div class="form-group">
<input name="username" required autocapitalize="none" minlength="2" type="text" class="form-control" placeholder="Email">
<!-- <div *ngIf="username.invalid && (username.dirty || username.touched)" class="alert alert-danger">-->
<!-- <div *ngIf="username.errors?.['required']">-->
<!-- Username is required.-->
<!-- </div>-->
<!-- <div *ngIf="username.errors?.['minlength']">-->
<!-- Username must be at least 4 characters long.-->
<!-- </div>-->
<!-- </div>-->
</div><!-- form-group -->
<div class="form-group">
<input name="password" required minlength="8" type="password" class="form-control" placeholder="Password">
<!-- <div *ngIf="password.invalid && (password.dirty || password.touched)" class="alert alert-danger">-->
<!-- <div *ngIf="password.errors?.['required']">-->
<!-- Password is required.-->
<!-- </div>-->
<!-- <div *ngIf="password.errors?.['minlength']">-->
<!-- Password must be at least 8 characters long.-->
<!-- </div>-->
<!-- </div>-->
</div><!-- form-group -->
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="exampleCheck1">
<label class="form-check-label" for="exampleCheck1">
I have read and agree to the Fasten Health <br/> <a href="https://policy.fastenhealth.com/privacy_policy.html">Privacy Policy</a>
and <a href="https://policy.fastenhealth.com/terms.html">Terms of Service</a>
</label>
</div>
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="exampleCheck2">
<label class="form-check-label" for="exampleCheck2">
Join Mailing List
</label>
</div>
<!-- <div *ngIf="errorMsg" class="alert alert-danger mt-3" role="alert">-->
<!-- <strong>Error</strong> {{errorMsg}}-->
<!-- </div>-->
</form>
</div><!-- az-signin-header -->
<div class="az-signin-footer">
<button type="submit" class="btn btn-az-primary btn-block">Create Account</button>
</div><!-- az-signin-footer -->
</div><!-- az-card-signin -->
</div><!-- az-signin-wrapper -->
</div>
</div>

View File

@ -0,0 +1,34 @@
.opacity-20 {
opacity: 0.2;
}
.nopadding {
padding: 1px !important;
margin: 0px !important;
}
.outer-div {
position: absolute;
//top:25%;
right: 0;
bottom: 0;
left: 0;
z-index: 13;
/*
* Setting all four values to 0 makes the element as big
* as its next relative parent. Usually this is the viewport.
*/
}
.inner-div {
margin: 0 auto;
//background-color: khaki;
}
.az-card-signin {
background-color: white;
width: 450px;
box-shadow: 0 0 50px 0 rgba(207, 207, 207, 0.5);
}

View File

@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AuthSignupWizardComponent } from './auth-signup-wizard.component';
describe('AuthSignupWizardComponent', () => {
let component: AuthSignupWizardComponent;
let fixture: ComponentFixture<AuthSignupWizardComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ AuthSignupWizardComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(AuthSignupWizardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,103 @@
import {Component, OnInit, ViewChild} from '@angular/core';
import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'app-auth-signup-wizard',
templateUrl: './auth-signup-wizard.component.html',
styleUrls: ['./auth-signup-wizard.component.scss']
})
export class AuthSignupWizardComponent implements OnInit {
gridImages: string[] = [
"f8f9ce28-d79b-4b54-9f7d-3f0aaba88c2c.png",
"89bb6993-b806-49a2-84e2-6e70705c504a.png",
"9fcc4529-7dc9-4c66-9198-574f978c8bb7.png",
"68952002-f17e-4086-aae5-841241b194dd.png",
"767b97b9-4538-433f-ab7a-14ccb0053323.png",
"74078880-4084-430e-bc6c-223e5990cef8.png",
"10668246-1077-4c1d-a6ce-0557c9476e77.png",
"f7e4fc08-c6f6-426b-be98-d60aa36d3b8b.png",
"65308856-beaa-46a0-9775-20c6c9322add.png",
"6e901e85-8f45-4c60-8d1f-12621aad07f1.png",
"e675376d-03de-4e66-8196-eaccda536ad5.png",
"a36fd256-2751-464f-b6d7-418279595b1e.png",
"c623f37e-6399-4a13-909f-3d9886130673.png",
"467592a3-7f5f-4258-909e-a99ca971ce15.png",
"5ad8a5ab-6570-4f1e-8002-30a051ec52c2.png",
"ddbef50d-3940-4411-9dea-6bf759704c6e.png",
"fc2dcde0-0848-4b09-aeaf-bfef58120de9.png",
"347c0df7-5817-470e-8b28-2802f90461f6.png",
"ec5bc181-5466-4ebd-9e42-471593b8d104.png",
"d3b1eba5-ec53-4e6d-9600-9510afbc4dda.png",
"16483fad-5c24-4766-ad53-bd78551f0768.png",
"ae8026ed-e74b-4bf3-9f53-458c250420ba.png",
"907d39f4-6b30-46cd-b0c8-f525c636c933.png",
"6b076b97-18f7-452d-9f09-20dffb01729f.png",
"c7feccc5-ad10-4aeb-91b0-12b6b93feeba.png",
"c66a7c1e-21f2-44aa-9486-cdfb5ad699ba.png",
"82af2366-1d27-4665-ba99-e5a60a75205a.png",
"2289e832-64da-47d9-82ef-1f4e15ccf627.png",
"26768525-2b04-4715-9159-3679598289a3.png",
"80af4067-77e9-4c13-b617-4f370dc14d3f.png",
"ec6c5f06-d7f8-4eac-8e2f-6cda4536d8ab.png",
"93ee1d70-6eaa-487b-84d1-cc18bcda253f.png",
"6d5ba4db-4b63-4277-bb80-dc278dbe28bd.png",
"b22e4e71-1121-4fca-b158-efbb906918e9.png",
"49fd46d0-05ce-4c7d-923c-3891935f6947.png",
"19652f82-98b9-44e6-9964-e426192a723d.png",
"314a06fc-4efc-4e34-8048-565455e4f3e1.png",
"8123cfc7-53b6-45d6-ace3-b64d4bd3234b.png",
"35159b16-a1b5-45ba-9d4f-83f471d5f44b.png",
"d6c0016f-aaec-4764-ac28-7a6eda64b693.png",
"d09c7811-213b-4c19-9154-48e57174f239.png",
"2bcdcc4c-0f13-4edb-85f4-2c9f4f948df0.png",
"4a4720a0-0efc-4b63-a83d-a8cc5b1c15ad.png",
"98f680b2-15c4-4854-902b-ed6b69425164.png",
"32283b0a-3c36-4f92-b9c2-dd2edf3a3db1.png",
"d56e9e82-3f62-4ce8-8a55-27da90fbe183.png",
"4fc37973-195c-4e25-8751-331a3b88e685.png",
"fb0bb8fa-8336-4b26-bdc5-7f8a432c1d94.png",
"7ca2d9d1-d300-479d-ab85-f956b6ef60de.png",
"4fd8bb55-bb2d-4748-a134-bbab7a22e4db.png",
"63cde119-f9d8-468d-900a-1976211739f8.png",
"e8290a84-88a1-4eac-a5b4-b2c63146b2c9.png",
"13b592f9-5c8b-4f90-aa54-5ab57a29ea89.png",
"0398ce8e-9200-430c-a654-f2057bc9a2d4.png",
"92b1d310-99a1-4de2-99b6-975eaf5a3744.png",
"418d563f-bd82-473f-a738-cd9775db4e56.png",
"8fb52893-1e93-4fea-adba-838e9b42e4d2.png",
"acec8466-8b0a-4adc-9929-561b7136fccb.png",
"3d01addb-1103-49ca-9c74-3027112e4aa8.png",
"5f5973bf-d11c-4f99-9b86-b1303cea3503.png",
"1317665c-e5c4-48b8-b3a5-2a90aa0283d7.png",
"48f2153e-6f4a-4da5-99a5-775a888c218a.png",
"34451b52-0f65-4e1a-91aa-5f2b1420f4b7.png",
"d3a10e7c-63c1-4309-b801-e42ce6e575d5.png",
"4c74937f-c30d-49c8-993e-c5a133f92414.png",
"5c4c748f-acd5-4fc8-b6cd-a37f629709fb.png",
"0293e1f1-291e-48ad-a5d0-cc7fcb062603.png",
"407f63d2-8fc7-42dd-9a46-23c76693789b.png",
"6d5de058-cc60-4f07-89db-bcc6817bb115.png",
"a1c9be32-3539-4390-bf01-828d5fb9f57d.png",
"562c8d0a-e524-49d7-81c2-70b34b4b9a15.png",
"8023b832-eaca-414a-9a53-c2fe423087d2.png",
"e8e73128-7722-4514-9684-1c17d43d880e.png",
"24cb81a7-dd2b-4b07-808b-f6611fea0393.png",
"5266bc57-58db-4171-8d73-a2a40ff380d2.png",
"9752c0a1-49f5-4842-8554-bfa3a6a3c3b4.png",
"df4a6dd3-672f-4547-8ade-609df28dcda9.png",
"921bb517-fdc9-4ca2-b9fc-a9e17e6cb8fc.png",
"e3f229a1-8637-49b1-abaa-84d228aff34a.png",
"53f22687-4635-4bff-99e2-2eacdc402359.png",
"c7fe32b2-97c6-45f7-90f8-47213c9b85f1.png",
"a7a87c72-1d8a-42d6-b0a4-c72b7dd8933a.png",
"2630415e-1871-437a-84de-52ad7ce88f3e.png",
"b53ff282-4725-45f7-a436-89f77320f062.png",
]
constructor() { }
ngOnInit(): void {
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

2
go.mod
View File

@ -15,7 +15,7 @@ require (
github.com/dave/jennifer v1.6.1
github.com/dominikbraun/graph v0.15.0
github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3
github.com/fastenhealth/fasten-sources v0.5.17
github.com/fastenhealth/fasten-sources v0.5.18
github.com/fastenhealth/gofhir-models v0.0.6
github.com/gin-gonic/gin v1.9.0
github.com/go-gormigrate/gormigrate/v2 v2.1.1

4
go.sum
View File

@ -101,8 +101,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fastenhealth/fasten-sources v0.5.17 h1:mNyv30uYkJVumIfHe+GcoMFITRT2Z4OrTSntGSCtJ9o=
github.com/fastenhealth/fasten-sources v0.5.17/go.mod h1:wD94lmBq6F2mIwT2CBF8owU4gO7E1oY2HUX6bbovOXM=
github.com/fastenhealth/fasten-sources v0.5.18 h1:o7WVAfJ8bbVQQojArgf3NWnfCp6roZOr9nCLpqGKM50=
github.com/fastenhealth/fasten-sources v0.5.18/go.mod h1:wD94lmBq6F2mIwT2CBF8owU4gO7E1oY2HUX6bbovOXM=
github.com/fastenhealth/gofhir-models v0.0.6 h1:yJYYaV1eJtHiGEfA1rXLsyOm/9hIi6s2cGoZzGfW1tM=
github.com/fastenhealth/gofhir-models v0.0.6/go.mod h1:xB8ikGxu3bUq2b1JYV+CZpHqBaLXpOizFR0eFBCunis=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=