diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 292b8976..1a37b528 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,7 +6,7 @@ go mod vendor go run backend/cmd/fasten/fasten.go start --config ./config.example.yaml --debug docker build -t fasten-couchdb -f docker/couchdb/Dockerfile . -docker run --rm -it -p 5984:5984 -v './.couchdb/data:/opt/couchdb/data' fasten-couchdb +docker run --rm -it -p 5984:5984 -v `pwd`/.couchdb/data:/opt/couchdb/data fasten-couchdb ``` # Docker diff --git a/backend/pkg/config/config.go b/backend/pkg/config/config.go index dde760b6..44b30d70 100644 --- a/backend/pkg/config/config.go +++ b/backend/pkg/config/config.go @@ -77,9 +77,5 @@ func (c *configuration) ReadConfig(configFilePath string) error { // This function ensures that required configuration keys (that must be manually set) are present func (c *configuration) ValidateConfig() error { - if !c.IsSet("web.jwt.encryptionkey") { - return errors.ConfigValidationError("`web.jwt.encryptionkey` configuration option must be set") - } - return nil } diff --git a/docker/couchdb/Dockerfile b/docker/couchdb/Dockerfile index 042870b6..d19542f5 100644 --- a/docker/couchdb/Dockerfile +++ b/docker/couchdb/Dockerfile @@ -11,6 +11,6 @@ RUN curl https://github.com/just-containers/s6-overlay/releases/download/v1.21.8 COPY /docker/couchdb/local.ini /opt/couchdb/etc/ COPY /docker/rootfs / -RUN rm -rf /etc/services/fasten #delete the fasten app from the couchdbase container. +RUN rm -rf /etc/services.d/fasten #delete the fasten app from the couchdbase container. ENTRYPOINT ["/init"] diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index d2533a22..472d8161 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -19,12 +19,11 @@ import { AuthSigninComponent } from './pages/auth-signin/auth-signin.component'; import { FormsModule } from '@angular/forms'; import { NgxDropzoneModule } from 'ngx-dropzone'; import { CanActivateAuthGuard } from './services/can-activate.auth-guard'; -import {FastenApiService} from './services/fasten-api.service'; import {FastenDbService} from './services/fasten-db.service'; import {Router} from '@angular/router'; import { SourceDetailComponent } from './pages/source-detail/source-detail.component'; -import {ResourceListComponent} from './components/resource-list/resource-list.component'; import { HighlightModule, HIGHLIGHT_OPTIONS } from 'ngx-highlightjs'; +import {AuthInterceptorService} from './services/auth-interceptor.service'; @NgModule({ declarations: [ @@ -51,6 +50,12 @@ import { HighlightModule, HIGHLIGHT_OPTIONS } from 'ngx-highlightjs'; HighlightModule ], providers: [ + { + provide: HTTP_INTERCEPTORS, + useClass: AuthInterceptorService, + multi: true, + deps: [FastenDbService, Router] + }, CanActivateAuthGuard, { provide: HIGHLIGHT_OPTIONS, diff --git a/frontend/src/app/services/auth-interceptor.service.ts b/frontend/src/app/services/auth-interceptor.service.ts new file mode 100644 index 00000000..8a60e0f4 --- /dev/null +++ b/frontend/src/app/services/auth-interceptor.service.ts @@ -0,0 +1,39 @@ +import { Injectable, Injector } from '@angular/core'; +import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http'; +import { FastenDbService } from './fasten-db.service'; +import {Router} from '@angular/router'; +import {Observable, of, throwError} from 'rxjs'; +import {catchError} from 'rxjs/operators'; + +@Injectable({ + providedIn: 'root' +}) + +// based on https://stackoverflow.com/questions/46017245/how-to-handle-unauthorized-requestsstatus-with-401-or-403-with-new-httpclient +export class AuthInterceptorService implements HttpInterceptor { + + constructor(private fastenDbService: FastenDbService, private router: Router) { } + + private handleAuthError(err: HttpErrorResponse): Observable { + //handle your auth error or rethrow + if (err.status === 401 || err.status === 403) { + //navigate /delete cookies or whatever + this.fastenDbService.Logout() + this.router.navigateByUrl(`/auth/signin`); + // if you've caught / handled the error, you don't want to rethrow it unless you also want downstream consumers to have to handle it as well. + return of(err.message); // or EMPTY may be appropriate here + } + return throwError(err); + } + + intercept(req: HttpRequest, next: HttpHandler): Observable> { + //only intercept requests to the fasten API, all other requests should be sent as-is + if(!req.url.startsWith('/api/secure/')){ + return next.handle(req) + } + + // catch the error, make specific functions for catching specific errors and you can chain through them with more catch operators + return next.handle(req).pipe(catchError(x=> this.handleAuthError(x))); //here use an arrow function, otherwise you may get "Cannot read property 'navigate' of undefined" on angular 4.4.2/net core 2/webpack 2.70 + + } +} diff --git a/frontend/src/app/services/fasten-db.service.ts b/frontend/src/app/services/fasten-db.service.ts index b24db8ed..bed5f257 100644 --- a/frontend/src/app/services/fasten-db.service.ts +++ b/frontend/src/app/services/fasten-db.service.ts @@ -86,9 +86,10 @@ export class FastenDbService extends PouchdbRepository { //if we have a local database, lets see if we have an active session to the remote database. const remotePouchDb = new PouchDB(this.getRemoteUserDb(localStorage.getItem("current_user")), {skip_setup: true}); const session = await remotePouchDb.getSession() - console.warn("IsAuthenticated? getSession() ====> ", !!session) + const isAuth = !!session?.userCtx?.name + console.warn("IsAuthenticated? getSession() ====> ", isAuth) - return !!session + return isAuth } catch (e) { return false }