Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Build a Beautiful CRUD App with Spring Boot and Angular

:And remove the groups fetching logic from app.component.ts:Add a route for the HomeComponent and GroupListComponent to app-routing.module.ts:Update the CSS in styles.css to have rules for the breadcrumb and alert classes:Run npm start in your app directory to see how everything looks. Click on Manage JUG Tour, and you should see a list of the default groups.To squish the Actions column to the right, add the following to group-list.component.css:Your Angular app should update itself as you make changes.It's great to see your Spring Boot API's data in your Angular app, but it's no fun if you can't modify it!Create a group-edit component and use Angular's HttpClient to fetch the group resource with the ID from the URL.Add a route for this component to app-routing.module.ts:Replace the code in group-edit.component.ts with the following:Create a model/event.ts file so this component will compile.Update model/group.ts to include the Event class.The GroupEditComponent needs to render a form, so update group-edit.component.html with the following:If you look closely, you'll notice this component allows you to edit events for a group. This component is an excellent example of how to handle nested objects in Angular.Update group-edit.component.css to make things look better on all devices:Now, with your Angular app running, you should be able to add and edit groups! Yaasss! 👏👏👏To make the navbar at the top use Angular Material colors, update app.component.html with the following:Since this is not a standalone component, you must import MatToolbarModule in app.module.ts.Make some adjustments in app.component.css to make the toolbar look nicer.Now the app fills the screen more, and the toolbar has matching colors.I love building simple CRUD apps to learn a new tech stack, but I think it's even cooler to build a secure one. So let's do that!Spring Security added support for OpenID Connect (OIDC) in version 5.0, circa 2017. This is awesome because it means you can use Spring Security to secure your app with a third-party identity provider (IdP) like Auth0. This is a much better option than trying to build your own authentication system and store user credentials.Add the Okta Spring Boot starter to do OIDC authentication in your pom.xml. This will also add Spring Security to your app.Install the Auth0 CLI (if you haven't already) and run auth0 login in a shell.Next, run auth0 apps create to register a new OIDC app with appropriate callbacks:Copy the returned values from this command into an .okta.env file:If you're on Windows, use set instead of export to set these environment variables and name the file .okta.env.bat:Add *.env to your .gitignore file so you don't accidentally expose your client secret.Then, run source .okta.env (or .okta.env.bat on Windows) to set these environment variables in your current shell.Finally, run ./mvnw (or mvnw on Windows) to start the app.TIP: You might have to run chmod +x mvnw to execute the Maven wrapper script.You can then open http://localhost:8080 in your favorite browser. You'll be redirected to authenticate and returned afterward. You'll see a 404 error from Spring Boot since you have nothing mapped to the default / route.To make Spring Security Angular-friendly, create a SecurityConfiguration.java file in src/main/java/.../jugtours/config. Create the config directory and put this class in it.This class has a lot going on, so let me explain a few things. In previous versions of Spring Security, there was an authorizeRequests() lambda you could use to secure paths. Since Spring Security 3.1, it's deprecated, and you should use authorizeHttpRequests(). The authorizeRequests() lambda is permissive by default, which means any paths you don't specify will be allowed. The recommended way, shown here with authorizeHttpRequests(), denies by default. This means you have to specify the resources you want to allow Spring Security to serve up, as well as the ones that the Angular app has.The requestMatchers line defines the URLs allowed for anonymous users. You will soon configure things so your Spring Boot app serves up your Angular app, hence the reason for allowing /, /index.html, and web files. You might also notice an exposed /api/user path.Configuring CSRF (cross-site request forgery) protection with CookieCsrfTokenRepository.withHttpOnlyFalse() means that the XSRF-TOKEN cookie won't be marked HTTP-only, so Angular can read it and send it back when it tries to manipulate data. The CsrfTokenRequestAttributeHandler is no longer the default, so you have to configure it as the request handler. To learn more, you can read this Stack Overflow answer. Basically, since we're not sending the CSRF token to an HTML page, we don't have to worry about BREACH attacks. This means we can revert to the previous default from Spring Security 5.You'll need to create the CookieCsrfFilter class that's added because Spring Security 6 no longer sets the cookie for you. Create it in the web package.Create src/main/java/.../jugtours/web/UserController.java and populate it with the following code. Angular will use this API to 1) find out if a user is authenticated and 2) perform global logout.You'll also want to add user information when creating groups so that you can filter by your JUG tour. Add a UserRepository.java in the same directory as GroupRepository.java.Add a new findAllByUserId(String id) method to GroupRepository.java.Then inject UserRepository into GroupController.java and use it to create (or grab an existing user) when adding a new group. While you're there, modify the groups() method to filter by user.To highlight the changes, please review the groups() and createGroup() methods above. I think it's pretty slick that Spring JPA will create the findAllByUserId() method/query for you.I like Angular because it's a secure-first framework. It has built-in support for CSRF, and it's easy to make it identity-aware. Let's do both!Angular's HttpClient supports the client-side half of the CSRF protection. It'll read the cookie sent by Spring Boot and return it in an X-XSRF-TOKEN header. You can read more about this at Angular's Security docs.Create a new AuthService class to communicate with your Spring Boot API for authentication information. Add the following code to a new file at app/src/app/auth.service.ts.Add the referenced User class to app/src/app/model/user.ts.Modify home.component.ts to use AuthService to see if the user is logged in.Modify home.component.html to show the Login button if the user is not logged in. Otherwise, show a Logout button.Update app/src/proxy.conf.js to have additional proxy paths for /oauth2 and /login.After all these changes, you should be able to restart both Spring Boot and Angular and witness the glory of securely planning your very own JUG Tour!To build and package your React app with Maven, you can use the frontend-maven-plugin and Maven's profiles to activate it. Add properties for versions and a section to your pom.xml.While you're at it, add the active profile setting to src/main/resources/application.properties:After adding this, you should be able to run mvn spring-boot:run -Pprod and see your app running at http://localhost:8080.If you start at the root, everything will work fine since Angular will handle routing. However, if you refresh the page when you're at http://localhost:8080/groups, you'll get a 404 error since Spring Boot doesn't have a route for /groups. To fix this, add a SpaWebFilter that conditionally forwards to the Angular app.And add to your SecurityConfiguration.java class:Now, if you restart and reload the page, everything will work as expected. 🤩In this section, you'll learn how to integrate Cypress into this project to support end-to-end tests. Add the Cypress Angular Schematic:Select the default updates when prompted. Then, update app/cypress/support/commands.ts to add a login(username, password) method:Update app/cypress/support/e2e.ts to log in before each test and log out after.Add a app/cypress/e2e/home.cy.ts test to verify that the home page loads.Create a groups.cy.ts in the same directory to test CRUD on groups.Add environment variables with your credentials to the .okta.env (or .okta.env.bat) file you created earlier.Then, run source .okta.env (or .okta.env.bat on Windows) to set these environment variables and start the app.In another terminal window, run the Cypress tests with Electron.If you run npm test, you'll see several failures. That's because the components have dependencies that aren't imported in the tests. Update home.component.spec.ts to import HttpClientTestingModule:In app.component.spec.ts, import MatToolBarModule and look for JUG Tours in the page.Then, update both group component tests to import HttpClientTestingModule and RouterTestingModule.Now, npm test should pass.If you run mvn test without setting environment variables, your Java tests will fail too. To fix this, add a src/test/java/com/okta/developer/jugtours/TestSecurityConfiguration.java class to mock the OAuth provider.Then, update JugToursApplicationTests.java in the same directory to use the new configuration.Run mvn test again, and your tests will pass. 🎉Add a GitHub workflow at .github/workflows/main.yml to prove that your tests run in CI.You can see this workflow in action on GitHub, or you can try it yourself by creating a new GitHub repo and pushing your code to it.Add environment variables for the above secrets to your GitHub repository at Settings > Secrets and variables > Actions > New Repository Secret.Push your changes to GitHub and watch the CI workflow run. ✅I hope this post has helped you learn how to build secure Angular and Spring Boot apps. Using OpenID Connect is a recommended practice for authenticating full-stack apps like this one, and Auth0 makes it easy to do. Adding CSRF protection and packaging your Spring Boot + Angular app as a single artifact is super cool too!We've written some other fun Spring Boot, Angular, and JHipster tutorials. Check them out!I've also written a couple of InfoQ mini-books that you might find useful:If you have any questions, please leave a comment below. If you want to see the completed code for this tutorial, check out its GitHub repo. Follow us on Twitter and YouTube for more content like this.Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well Confirm For further actions, you may consider blocking this person and/or reporting abuse jazzybruno - Jul 4 coder4life - Jun 1 Jean Santos - Jul 3 Samuel Appiah Kojo - Jul 3 Authenticate, manage, and secure users in any application within minutes. Once suspended, oktadev will not be able to comment or publish posts until their suspension is removed. Once unsuspended, oktadev will be able to comment and publish posts again. Once unpublished, all posts by oktadev will become hidden and only accessible to themselves. If oktadev is not suspended, they can still re-publish their posts from their dashboard. Note: Once unpublished, this post will become invisible to the public and only accessible to Matt Raible. They can still re-publish the post if they are not suspended. Thanks for keeping DEV Community safe. Here is what you can do to flag oktadev: oktadev consistently posts content that violates DEV Community's code of conduct because it is harassing, offensive or spammy. Unflagging oktadev will restore default visibility to their posts. DEV Community — A constructive and inclusive social network for software developers. With you every step of your journey. Built on Forem — the open source software that powers DEV and other inclusive communities.Made with love and Ruby on Rails. DEV Community © 2016 - 2023. We're a place where coders share, stay up-to-date and grow their careers.



This post first appeared on VedVyas Articles, please read the originial post: here

Share the post

Build a Beautiful CRUD App with Spring Boot and Angular

×

Subscribe to Vedvyas Articles

Get updates delivered right to your inbox!

Thank you for your subscription

×