Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
919da49
Import from starter.spring.io
bigfei May 21, 2023
9b3e8b5
feat(api): Add UserRepository & UserService & UserController
bigfei May 21, 2023
92c8ba2
feat(api): add jacoco for test coverage and more test for UserService
bigfei May 22, 2023
775e3bf
feat(oauth2): Add auth0.com for oauth2 support.
bigfei May 23, 2023
545ef79
feat(oauth2): add more test around UserController and add syncUser wh…
bigfei May 24, 2023
d2b94d1
feat(follow): add follow apis and tests.
bigfei May 25, 2023
f7fc6a6
feat(nearme): Add nearme API using mongodb geoNear func.
bigfei May 25, 2023
96de104
feat(docker): add docker-compose.yml.
bigfei May 25, 2023
b8c4c03
fix(docker): add docker-compose init file for mongodb
bigfei May 26, 2023
52946c3
fix(docs): Improve the doc.
bigfei May 26, 2023
d6b71d0
fix(syncuser): fix the user sync when logining.
bigfei May 26, 2023
0eaebc7
refactor(import): Optimize importing
bigfei May 26, 2023
34f4fc3
feat(ci): add github actions
bigfei May 30, 2023
2d91910
fix(ci): move into workflows
bigfei May 30, 2023
7f9e6c9
fix(ci): add check for master branch and remove it from docker tags.
bigfei May 30, 2023
50a23ef
fix(ci): upgrade to latest version of actions to remove warning.
bigfei May 30, 2023
7f00b76
fix(ci): use new format to set outputs
bigfei May 30, 2023
813d7da
refactor(ci): add test.yml and use embedded mongo
bigfei May 31, 2023
3e28c6b
fix(ci): add perm settings on ci.yml
bigfei Jun 1, 2023
9cac947
fix(ci): add codecov badge.
bigfei Jun 1, 2023
8ed4f38
fix(ci): use img.shields.io for badge .
bigfei Jun 1, 2023
1ac8604
fix(ci): add dependabot
bigfei Jun 1, 2023
5a0f952
fix(ci): Update dependabot.yml
bigfei Jun 1, 2023
e90b4ab
build(deps): bump okta-spring-boot-starter from 3.0.3 to 3.0.4
dependabot[bot] Jun 1, 2023
afdc644
build(deps): bump json from 20220924 to 20230227
dependabot[bot] Jun 1, 2023
ce95ee6
fix(ci): cache maven dependency
bigfei Jun 1, 2023
7341cb1
fix(ci): cache embedded mongo
bigfei Jun 1, 2023
73900f9
build(deps-dev): bump de.flapdoodle.embed.mongo.spring30x
dependabot[bot] Jun 2, 2023
8cfcdb2
build(deps): bump json from 20230227 to 20230618
dependabot[bot] Jun 19, 2023
8f293d8
build(deps): bump spring-boot-starter-parent from 3.1.0 to 3.1.1
dependabot[bot] Jun 23, 2023
0296c0a
build(deps): bump org.springframework.boot:spring-boot-starter-parent
dependabot[bot] Jul 21, 2023
61d2520
build(deps): bump com.okta.spring:okta-spring-boot-starter
dependabot[bot] Aug 18, 2023
18a575c
build(deps-dev): bump de.flapdoodle.embed:de.flapdoodle.embed.mongo.s…
dependabot[bot] Aug 21, 2023
929c1b4
add some tests
bigfei Dec 6, 2023
0f3ef38
build(deps-dev): bump de.flapdoodle.embed:de.flapdoodle.embed.mongo.s…
dependabot[bot] Nov 20, 2023
aa380e2
build(deps): bump org.springframework.boot:spring-boot-starter-parent
dependabot[bot] Oct 20, 2023
bcfaf06
build(deps): bump org.jacoco:jacoco-maven-plugin from 0.8.10 to 0.8.11
dependabot[bot] Oct 17, 2023
622f587
build(deps): bump org.json:json from 20230618 to 20231013
dependabot[bot] Oct 16, 2023
61b0edd
build(deps): bump docker/setup-buildx-action from 2 to 3
dependabot[bot] Sep 13, 2023
c638585
build(deps): bump docker/login-action from 2 to 3
dependabot[bot] Sep 12, 2023
6088943
build(deps): bump actions/checkout from 3 to 4
dependabot[bot] Sep 5, 2023
c89065a
Add unit tests for AuthController, GlobalExceptionHandler, LogoutCont…
bigfei Jun 14, 2025
ac72cf8
build(deps): update Codecov and upload-artifact actions to latest ver…
bigfei Jun 14, 2025
6e42ed3
fix(deps): update de.flapdoodle.embed.mongo dependency to version 4.20.0
bigfei Jun 14, 2025
13dc9a5
fix(ci): install libssl1.1 in CI workflow
bigfei Jun 14, 2025
41696c7
fix(ci): update CI to use Ubuntu 22.04 and improve libssl1.1 installa…
bigfei Jun 14, 2025
f4315a0
fix(ci): ensure Codecov action uses the correct token and verbose mode
bigfei Jun 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target
21 changes: 21 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
version: 2
updates:
- package-ecosystem: maven
directory: "/"
schedule:
interval: daily
time: "15:40"
timezone: "Asia/Shanghai"
open-pull-requests-limit: 10
labels:
- dependencies

- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: daily
time: "15:40"
timezone: "Asia/Shanghai"
open-pull-requests-limit: 10
labels:
- dependencies
57 changes: 57 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: CI

on:
pull_request:
push:
branches: [master]

permissions:
contents: write

concurrency:
group: ci-${{ github.ref }}-group
cancel-in-progress: true

jobs:
default:
runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v4
- name: Install libssl1.1
run: |
echo "deb http://security.ubuntu.com/ubuntu focal-security main" | sudo tee /etc/apt/sources.list.d/focal-security.list
sudo apt-get update && sudo apt-get install -y libssl1.1
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: 'maven'
- name: Cache embedded mongo
id: cache-mongo
uses: actions/cache@v3
env:
cache-name: cache-mongo
with:
path: ~/.embedmongo
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/application-test.yml') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Submit Dependency Snapshot
uses: advanced-security/maven-dependency-submission-action@v3
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
- name: Save Jar file
uses: actions/upload-artifact@v4
with:
name: wc-api-jar
path: target/*.jar
retention-days: 14
44 changes: 44 additions & 0 deletions .github/workflows/docker-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: docker-release

on:
push:
branches:
- "master"
tags:
- "v*"

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Docker Login
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Prepare build tag
id: tag
run: |
IMAGE=${{ secrets.DOCKER_HUB_USERNAME }}/wc-api
if [ -z "${GITHUB_REF_NAME}" ] || [ "${GITHUB_REF_NAME}" = "master" ]; then
TAGS="${IMAGE}:latest"
else
TAGS=`echo ${IMAGE}:latest --tag ${IMAGE}:${GITHUB_REF_NAME}`
fi
echo "TAGS=${TAGS}" >> $GITHUB_OUTPUT

- name: Build and push
run: >-
docker buildx build
--file ./Dockerfile
--platform linux/amd64,linux/arm64
--tag ${{ steps.tag.outputs.TAGS }}
--push .
38 changes: 38 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/

### VS Code ###
.vscode/

### Mac OS ###
.DS_Store

.history
1 change: 1 addition & 0 deletions .java-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
17.0
Binary file added .mvn/wrapper/maven-wrapper.jar
Binary file not shown.
18 changes: 18 additions & 0 deletions .mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.1/apache-maven-3.9.1-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
13 changes: 13 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM eclipse-temurin:17-jdk-jammy as builder
WORKDIR /opt/app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
COPY ./src ./src
RUN ./mvnw -Dmaven.test.skip=true clean package

FROM eclipse-temurin:17-jre-jammy
WORKDIR /opt/app
EXPOSE 8080
COPY --from=builder /opt/app/target/*.jar /opt/app/*.jar
ENTRYPOINT ["java", "-jar", "/opt/app/*.jar" ]
161 changes: 94 additions & 67 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,73 +1,100 @@
# Wiredcraft Back-end Developer Test
![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/bigfei/test-backend-java/docker-release.yml)
[![Codecov branch](https://img.shields.io/codecov/c/github/bigfei/test-backend-java/master?token=YACNVNL1OB)](https://codecov.io/gh/bigfei/test-backend-java)

Make sure you read the whole document carefully and follow the guidelines in it.
## Introduction
It is a simple LBS service that offers nearby searches, following/followers lists,
and profile updates, according to the [Requirement](docs/REQ.md).

## Context

Build a RESTful API that can `get/create/update/delete` user data from a persistence database

### User Model

```
{
"id": "xxx", // user ID
"name": "test", // user name
"dob": "", // date of birth
"address": "", // user address
"description": "", // user description
"createdAt": "" // user created date
}
## Quick Start and Demo
### Prerequisite
1. Run docker-compose to setup a mongodb server:
```shell
docker-compose up -d --build
```
After the mongodb get started, login into `http://localhost:8081` to verify the db collections status:
![Step1](docs/m1.png)
then change the mongodb settings in file `src/main/resources/application.yml` accordingly.
2. Register an auth0.com account and app for oauth2 integration.
1. Visit auth0.com and create an app as follows: ![Step1](docs/s1.png)
2. Copy the domain / ClientID / ClientSecret from the settings page: ![Step2](docs/s2.png)
3. Add the callback Urls and logout Urls on settings page: ![Step2](docs/s3.png)
3. Modify the `src/main/resources/application.yml` with the auth0 settings from the last step.
3. Run `./mvnw spring-boot:run` to start the app.

### Demo
Or if you want just to feel the app, visit `https://wc-api.bigfei.me`.

## Under the hood
### Tech Stack
- **MongoDB** Use mongodb as the DB for faster searches and [geospatial](https://www.mongodb.com/docs/manual/reference/operator/aggregation/geoNear/) functions.
- **Springboot Framework** as the de factro for Java world to build any restful api things.
- Use jWT and **Auth0** as the oauth2 provider for prototype building and MVP.
- **Github Actions** are used for CI solution.
- Cloudflare Tunnel for free https access and CDN services.
- Docker for deployment and testing.
- **Thymeleaf** adds support for Server-Side View Rendering.
- **Sentry** for logging APM.

## System design and User Story

### User Restful API

| Method | Endpoints | Usage |
|--------|----------------|--------------------------------------------|
| POST | /users | create a User |
| GET | /users | list Users |
| GET | /users/{id} | list single User |
| PUT | /users/{id} | update a User |
| DELETE | /users/{id} | delete a User |
| GET | /users/profile | show a profile page for current logon user |
| GET | /users/me | show user details for current user |

### OAuth2
Use auth0.com as the backend oauth provider and okta-spring-boot-starter for springboot supports.
See the config details from the [Prerequisite](#prerequisite)

### Followers/Friend List
Add a mongodb collection as the follower/followee relationship.
Use [DBRef](https://www.mongodb.com/docs/manual/reference/database-references/)
for mapping the reference relationship.

| follows | |
|-----------|---|
| followee | |
| follower | |
| createdAt | |

APIs:

| Method | Endpoints | Usage |
|--------|--------------------------------|-------------------------------------------------------------|
| GET | /users/{id}/followers | a list of users who are followers of the specified user ID. |
| GET | /users/{id}/following | a list of users the specified user ID is following |
| POST | /users/{id}/following/{target} | let a user to follow another user |
| DELETE | /users/{id}/following/{target} | let a user to unfollow another user |

### Near me
Use mongodb geospatial search to do geo search around a specific geo points (aka geocaches).
1. Friends: they are following each other.
2. Nearme: Near the location point using geo search (`$geoNear`).

APIs:

| Method | Endpoints | Usage |
|--------|---------------------------------------|-------------------------------------------------------------------|
| GET | /users/{id}/nearFriends?distanceKm=10 | a list of friends within a distance of 10 kilometers from userId. |


## Todos and Caveats

### Backlog
- [ ] Sentry APM integration.
- [x] Github Actions CI.
- [ ] Swagger API docs.
- [ ] Put secrets into .env file for safety.

### Caveats
1. Use Mongodb match/in pipelines for checking a user friends list rather than naive recursive searching.

## Requirements

### Functionality

- The API should follow typical RESTful API design pattern.
- The data should be saved in the DB.
- Provide proper unit test.
- Provide proper API document.

### Tech stack

- Use Java and any framework.
- Use any DB.

### Bonus

- Write clear documentation on how it's designed and how to run the code.
- Write good in-code comments.
- Write good commit messages.
- An online demo is always welcome.

### Advanced requirements

*These are used for some further challenges. You can safely skip them if you are not asked to do any, but feel free to try out.*

- Provide a complete user auth (authentication/authorization/etc.) strategy, such as OAuth. This should provide a way to allow end users to securely login, autenticate requests and only access their own information.
- Provide a complete logging (when/how/etc.) strategy.
- Imagine we have a new requirement right now that the user instances need to link to each other, i.e., a list of "followers/following" or "friends". Can you find out how you would design the model structure and what API you would build for querying or modifying it?
- Related to the requirement above, suppose the address of user now includes a geographic coordinate(i.e., latitude and longitude), can you build an API that,
- given a user name
- return the nearby friends


## What We Care About

Feel free to use any open-source library as you see fit, but remember that we are evaluating your coding skills and problem solving skills.

Here's what you should aim for:

- Good use of current Java & API design best practices.
- Good testing approach.
- Extensible code.

## FAQ

> Where should I send back the result when I'm done?

Fork this repo and send us a pull request when you think it's ready for review. You don't have to finish everything prior and you can continue to work on it. We don't have a deadline for the task.

> What if I have a question?

Feel free to make your own assumptions about the scope of this task but try to document those. You can also reach to us for questions.
Loading