This is a simple project with server side code written in Swift. It contains few concepts which can/should have production ready server side application. Especially it focuses on:
- MVC pattern - described on Medium article
- Unit tests - described on Medium article
- Configuration files - described on Medium article
- Data access (ORM) - described on Medium article
- Services, Repositories & Data validation - described on Medium article
- Authentication & Authorization - described on Medium article
- Resource based authorization - described on Medium article
- Docker on Azure - described on Medium article
- Continuous Integration - described on Medium article
- OpenAPI (Swagger) - described on Medium article
Verify that you have Swift installed: swift --version
. Command should produce message similar to this one:
Apple Swift version 4.0 (swiftlang-900.0.65 clang-900.0.37)
Target: x86_64-apple-macosx10.9
If Swift is not installed on you computer follow the steps described on Swift.org.
macOS Everything you need is already installed.
Ubuntu Linux Perfect runs in Ubuntu Linux 16.04 environments. Perfect relies on OpenSSL, libssl-dev, and uuid-dev. To install these, in the terminal, type:
sudo apt-get install openssl libssl-dev uuid-dev
Now you’re ready to build application. The following will clone and build project. It will launch a local server that will run on port 8181 on your computer:
git clone https://github.com/mczachurski/TaskServerSwift.git
cd TaskServerSwift
swift build
.build/debug/TaskServerSwift
The server is now running and waiting for connections. Access http://localhost:8181/ to see the greeting. Hit "control-c" to terminate the server.
Below there is a description of all API endpoints which exists in the application.
Actions in health controller.
Endpoint which returns information about application status.
Method | GET |
Uri | /health |
Authorization | anonymous |
Response example:
{
"message": "I'm fine and running!"
}
Curl:
curl -X GET \
http://localhost:8181/health \
-H 'Cache-Control: no-cache'
Controller with actions for managing user account.
Endpoint where user can create a new account in the system.
Method | POST |
Uri | /account/register |
Authorization | anonymous |
Request example:
{
"name": "John Doe",
"email": "[email protected]",
"password": "p@ssw0rd",
"isLocked": false
}
Response example:
{
"email": "[email protected]",
"id": "8A267133-E50F-442D-AEFF-6C388E4D87C7",
"roles": [],
"name": "John Doe",
"isLocked": false
}
Curl:
curl -X POST \
http://localhost:8181/account/register \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json' \
-d '{
"name": "John Doe",
"email": "[email protected]",
"password": "p@ssw0rd",
"isLocked": false
}'
Endpoint for signing in into the system. Endpoint returns JWT token which can be used for all further communication.
Method | POST |
Uri | /account/sign-in |
Authorization | anonymous |
Request example:
{
"email": "[email protected]",
"password": "p@ssw0rd"
}
Response example:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiam9obi5kb2VAc29tZS1lbWFpbC5jb20iLCJpc3MiOiJ0YXNrZXItc2VydmVyLWlzc3VlciIsImlhdCI6MTUyMDY2OTE5MS43NDc5LCJleHAiOjE1MjA3MDUxOTEuNzQ3OSwicm9sZXMiOltdLCJ1aWQiOiIzNTk0NTc2NS00QTYxLTQ2NjEtOUVBQS04NTcwRjY1RTQ1OTgifQ.UorB8ZT2gU7LCp4pagiTeVVMqs0e5KHC04zi2wsvRmg"
}
Curl:
curl -X POST \
http://localhost:8181/account/sign-in \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json' \
-d '{
"email": "[email protected]",
"password": "p@ssw0rd"
}'
Endpoint where user can change his password to the system.
Method | POST |
Uri | /account/changePassword |
Authorization | signed in |
Request example:
{
"email": "[email protected]",
"password": "p@ssw0rd"
}
Curl:
curl -X POST \
http://localhost:8181/account/changePassword \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiam9obi5kb2VAc29tZS1lbWFpbC5jb20iLCJpc3MiOiJ0YXNrZXItc2VydmVyLWlzc3VlciIsImlhdCI6MTUyMDY2OTE5MS43NDc5LCJleHAiOjE1MjA3MDUxOTEuNzQ3OSwicm9sZXMiOltdLCJ1aWQiOiIzNTk0NTc2NS00QTYxLTQ2NjEtOUVBQS04NTcwRjY1RTQ1OTgifQ.UorB8ZT2gU7LCp4pagiTeVVMqs0e5KHC04zi2wsvRmg' \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json' \
-d '{
"email": "[email protected]",
"password": "p@ssw0rd"
}'
Controller with actions for managing tasks.
Endpoint returns all tasks from system.
Method | GET |
Uri | /tasks |
Authorization | signed in |
Response example:
[
{
"id": "6DEB0425-DE7E-4F8E-9674-6139B05883EC",
"name": "Create new controllers",
"isFinished": false
},
{
"id": "C046B24B-92DC-4712-B434-98C1C2D19295",
"name": "Create authorization",
"isFinished": false
}
]
Curl:
curl -X GET \
http://localhost:8181/tasks \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiam9obi5kb2VAc29tZS1lbWFpbC5jb20iLCJpc3MiOiJ0YXNrZXItc2VydmVyLWlzc3VlciIsImlhdCI6MTUyMDY2OTE5MS43NDc5LCJleHAiOjE1MjA3MDUxOTEuNzQ3OSwicm9sZXMiOltdLCJ1aWQiOiIzNTk0NTc2NS00QTYxLTQ2NjEtOUVBQS04NTcwRjY1RTQ1OTgifQ.UorB8ZT2gU7LCp4pagiTeVVMqs0e5KHC04zi2wsvRmg' \
-H 'Cache-Control: no-cache'
Endpoint returns specific tasks by his identifier (id).
Method | GET |
Uri | /tasks/{id} |
Authorization | signed in |
Response example:
{
"id": "6DEB0425-DE7E-4F8E-9674-6139B05883EC",
"name": "Create new controllers",
"isFinished": false
}
Curl:
curl -X GET \
http://localhost:8181/tasks/6DEB0425-DE7E-4F8E-9674-6139B05883EC \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiam9obi5kb2VAc29tZS1lbWFpbC5jb20iLCJpc3MiOiJ0YXNrZXItc2VydmVyLWlzc3VlciIsImlhdCI6MTUyMDY2OTE5MS43NDc5LCJleHAiOjE1MjA3MDUxOTEuNzQ3OSwicm9sZXMiOltdLCJ1aWQiOiIzNTk0NTc2NS00QTYxLTQ2NjEtOUVBQS04NTcwRjY1RTQ1OTgifQ.UorB8ZT2gU7LCp4pagiTeVVMqs0e5KHC04zi2wsvRmg' \
-H 'Cache-Control: no-cache'
Endpoint for creating new tasks in the system.
Method | POST |
Uri | /tasks |
Authorization | signed in |
Request example:
{
"name": "Create new controllers",
"isFinished": false
}
Response example:
{
"id": "6DEB0425-DE7E-4F8E-9674-6139B05883EC",
"name": "Create new controllers",
"isFinished": false
}
Curl:
curl -X POST \
http://taskerserverswift.azurewebsites.net/tasks \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiam9obi5kb2VAc29tZS1lbWFpbC5jb20iLCJpc3MiOiJ0YXNrZXItc2VydmVyLWlzc3VlciIsImlhdCI6MTUyMDY2OTE5MS43NDc5LCJleHAiOjE1MjA3MDUxOTEuNzQ3OSwicm9sZXMiOltdLCJ1aWQiOiIzNTk0NTc2NS00QTYxLTQ2NjEtOUVBQS04NTcwRjY1RTQ1OTgifQ.UorB8ZT2gU7LCp4pagiTeVVMqs0e5KHC04zi2wsvRmg' \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json' \
-d '{
"name": "Create new controllers",
"isFinished": false
}'
Endpoint for updating tasks
Method | PUT |
Uri | /tasks/{id} |
Authorization | signed in |
Request example:
{
"id": "6DEB0425-DE7E-4F8E-9674-6139B05883EC",
"name": "Create new actions",
"isFinished": false
}
Response example:
{
"id": "6DEB0425-DE7E-4F8E-9674-6139B05883EC",
"name": "Create new actions",
"isFinished": false
}
Curl:
curl -X PUT \
http://localhost:8181/tasks/6DEB0425-DE7E-4F8E-9674-6139B05883EC \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiam9obi5kb2VAc29tZS1lbWFpbC5jb20iLCJpc3MiOiJ0YXNrZXItc2VydmVyLWlzc3VlciIsImlhdCI6MTUyMDY2OTE5MS43NDc5LCJleHAiOjE1MjA3MDUxOTEuNzQ3OSwicm9sZXMiOltdLCJ1aWQiOiIzNTk0NTc2NS00QTYxLTQ2NjEtOUVBQS04NTcwRjY1RTQ1OTgifQ.UorB8ZT2gU7LCp4pagiTeVVMqs0e5KHC04zi2wsvRmg' \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json' \
-d '{
"id": "6DEB0425-DE7E-4F8E-9674-6139B05883EC",
"name": "Create new actions",
"isFinished": false
}'
Endpoint where user can delete his tasks.
Method | DELETE |
Uri | /tasks/{id} |
Authorization | signed in |
Curl:
curl -X DELETE \
http://localhost:8181/tasks/6DEB0425-DE7E-4F8E-9674-6139B05883EC \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiam9obi5kb2VAc29tZS1lbWFpbC5jb20iLCJpc3MiOiJ0YXNrZXItc2VydmVyLWlzc3VlciIsImlhdCI6MTUyMDY2OTE5MS43NDc5LCJleHAiOjE1MjA3MDUxOTEuNzQ3OSwicm9sZXMiOltdLCJ1aWQiOiIzNTk0NTc2NS00QTYxLTQ2NjEtOUVBQS04NTcwRjY1RTQ1OTgifQ.UorB8ZT2gU7LCp4pagiTeVVMqs0e5KHC04zi2wsvRmg' \
-H 'Cache-Control: no-cache'
Controller with actions for managing users.
Endpoint returns users registered into the system.
Method | GET |
Uri | /users |
Authorization | signed in (Administrator) |
Response example:
[
{
"email": "[email protected]",
"id": "35945765-4A61-4661-9EAA-8570F65E4598",
"name": "John Doe",
"isLocked": false
},
{
"email": "[email protected]",
"id": "8A267133-E50F-442D-AEFF-6C388E4D87C7",
"name": "Emma Doe",
"isLocked": false
}
]
Curl:
curl -X GET \
http://localhost:8181/users \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiam9obi5kb2VAc29tZS1lbWFpbC5jb20iLCJpc3MiOiJ0YXNrZXItc2VydmVyLWlzc3VlciIsImlhdCI6MTUyMDY3MTI2Ny40NDQ4OCwiZXhwIjoxNTIwNzA3MjY3LjQ0NDg4LCJyb2xlcyI6WyJVc2VyIiwiQWRtaW5pc3RyYXRvciJdLCJ1aWQiOiIzNTk0NTc2NS00QTYxLTQ2NjEtOUVBQS04NTcwRjY1RTQ1OTgifQ.JrWb8ePBO1zBKDApXnYF4hJzZxkrTOjZ9fbUMUEvrYc' \
-H 'Cache-Control: no-cache'
Endpoint returns specific user by his identifier (id).
Method | GET |
Uri | /users/{id} |
Authorization | signed in (Administrator) |
Response example:
{
"email": "[email protected]",
"id": "35945765-4A61-4661-9EAA-8570F65E4598",
"roles": [
"User",
"Administrator"
],
"name": "John Doe",
"isLocked": false
}
Curl:
curl -X GET \
http://localhost:8181/users/35945765-4A61-4661-9EAA-8570F65E4598 \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiam9obi5kb2VAc29tZS1lbWFpbC5jb20iLCJpc3MiOiJ0YXNrZXItc2VydmVyLWlzc3VlciIsImlhdCI6MTUyMDY3MTI2Ny40NDQ4OCwiZXhwIjoxNTIwNzA3MjY3LjQ0NDg4LCJyb2xlcyI6WyJVc2VyIiwiQWRtaW5pc3RyYXRvciJdLCJ1aWQiOiIzNTk0NTc2NS00QTYxLTQ2NjEtOUVBQS04NTcwRjY1RTQ1OTgifQ.JrWb8ePBO1zBKDApXnYF4hJzZxkrTOjZ9fbUMUEvrYc' \
-H 'Cache-Control: no-cache'
Endpoint for creating new user.
Method | POST |
Uri | /users |
Authorization | signed in (Administrator) |
Request example:
{
"name": "Victor Doe",
"email": "[email protected]",
"password": "p@ssw0rd",
"isLocked": false
}
Response example:
{
"email": "[email protected]",
"id": "58ABCB3F-21D3-44AE-8B85-07D4AC1174B6",
"roles": [],
"name": "Victor Doe",
"isLocked": false
}
Curl:
curl -X POST \
http://localhost:8181/users \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiam9obi5kb2VAc29tZS1lbWFpbC5jb20iLCJpc3MiOiJ0YXNrZXItc2VydmVyLWlzc3VlciIsImlhdCI6MTUyMDY3MTI2Ny40NDQ4OCwiZXhwIjoxNTIwNzA3MjY3LjQ0NDg4LCJyb2xlcyI6WyJVc2VyIiwiQWRtaW5pc3RyYXRvciJdLCJ1aWQiOiIzNTk0NTc2NS00QTYxLTQ2NjEtOUVBQS04NTcwRjY1RTQ1OTgifQ.JrWb8ePBO1zBKDApXnYF4hJzZxkrTOjZ9fbUMUEvrYc' \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json' \
-d '{
"name": "Victor Doe",
"email": "[email protected]",
"password": "p@ssw0rd",
"isLocked": false
}'
Endpoint for updating user data.
Method | PUT |
Uri | /users/{id} |
Authorization | signed in (Administrator) |
Request example:
{
"email": "[email protected]",
"id": "58ABCB3F-21D3-44AE-8B85-07D4AC1174B6",
"name": "Victor Doe",
"isLocked": false,
"roles": [
"User", "Administrator"
]
}
Response example:
{
"email": "[email protected]",
"id": "58ABCB3F-21D3-44AE-8B85-07D4AC1174B6",
"name": "Victor Doe",
"isLocked": false,
"roles": [
"User", "Administrator"
]
}
Curl:
curl -X PUT \
http://localhost:8181/users/58ABCB3F-21D3-44AE-8B85-07D4AC1174B6 \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiam9obi5kb2VAc29tZS1lbWFpbC5jb20iLCJpc3MiOiJ0YXNrZXItc2VydmVyLWlzc3VlciIsImlhdCI6MTUyMDY3MTI2Ny40NDQ4OCwiZXhwIjoxNTIwNzA3MjY3LjQ0NDg4LCJyb2xlcyI6WyJVc2VyIiwiQWRtaW5pc3RyYXRvciJdLCJ1aWQiOiIzNTk0NTc2NS00QTYxLTQ2NjEtOUVBQS04NTcwRjY1RTQ1OTgifQ.JrWb8ePBO1zBKDApXnYF4hJzZxkrTOjZ9fbUMUEvrYc' \
-H 'Cache-Control: no-cache' \
-H 'Content-Type: application/json' \
-d '{
"email": "[email protected]",
"id": "58ABCB3F-21D3-44AE-8B85-07D4AC1174B6",
"name": "Victor Doe",
"isLocked": false,
"roles": [
"User", "Administrator"
]
}'
Endpoint for deleting users from the system.
Method | DELETE |
Uri | /users/{id} |
Authorization | signed in (Administrator) |
Curl:
curl -X DELETE \
http://localhost:8181/users/58ABCB3F-21D3-44AE-8B85-07D4AC1174B6 \
-H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiam9obi5kb2VAc29tZS1lbWFpbC5jb20iLCJpc3MiOiJ0YXNrZXItc2VydmVyLWlzc3VlciIsImlhdCI6MTUyMDY3MTI2Ny40NDQ4OCwiZXhwIjoxNTIwNzA3MjY3LjQ0NDg4LCJyb2xlcyI6WyJVc2VyIiwiQWRtaW5pc3RyYXRvciJdLCJ1aWQiOiIzNTk0NTc2NS00QTYxLTQ2NjEtOUVBQS04NTcwRjY1RTQ1OTgifQ.JrWb8ePBO1zBKDApXnYF4hJzZxkrTOjZ9fbUMUEvrYc' \
-H 'Cache-Control: no-cache'