# Customer Milestone 3
<img width="1920" alt="Milestone 3 Cover" src="https://github.com/bounswe/bounswe2024group11/assets/68506701/61bf5d12-a5df-45c2-ac83-aba953a0389d">
<!-- To be changed -->
## Description
This is the third milestone report for the `bounswe2024group11` team.
It includes a summary of what we have done, the implementation of the deployed application, the final design diagrams, final project plan in a detailed manner, lessons we have learnt, difficulties we have faced, work done by each team member, and the tools we have benefitted.
At the end of the report, we have dedicated a section for our self evaluation.
## 1. Executive Summary
### Summary
This project aims to build a comics-specific semantic information browser (SIB). Users will be able to create posts and search for them. The system will use Wikidata API to support the semantic searching of posts as well as enrich the app by providing metadata information.
Users will be able to register and login to the system so that they can make a short post, bookmark or like posts. They will also be able to see those who posted or liked content and follow them.
The system will use Wikidata API to make semantic queries to the Wikidata Database. Utilizing "subject-predicate-object" nature of these SPARQL queries, the system can search for objects that has semantic relations.
Our solution will provide an API that will be used by Web and Mobile clients. Hence, the system will provide a web and a mobile application.
### Current Status
#### Completed Requirements On Frontend
##### 1.1 User Requirements
* 1.1.1 Account Requirements
* 1.1.1.1 Users shall be able to register the system by providing a username, email, and password.
* 1.1.1.2 Registered users shall be able to log in to the system by providing username and password.
* 1.1.1.5 Registered users shall be able to log out from the system.
* 1.1.1.6 Registered users should have a profile page.
* 1.1.2 Post Requirements
* 1.1.2.1 Create
* 1.1.2.1.3 Users shall be able to see the author of the post.
##### 1.2 System Requirements
* 1.2.2 Feed
* 1.2.2.1 The system should provide a feed for users.
* 1.2.2.1.2 The system should show the registered user's followings' recently published posts to the registered user.
* 1.2.3 Authentication
* 1.2.3.1 The system shall only allow a username and an email address that is not used before upon registration.
* 1.2.3.3 The system shall hash users' authentication information.
### Scenarios
#### Scenario 1
- Emre registers to the app.
<img height=600 src="https://hackmd.io/_uploads/S1iIzRNXA.jpg">
- Emre uses his credentials to login.
<img height=600 src="https://hackmd.io/_uploads/SkqLm0N7R.jpg">
- Emre looks his profile. He decides to edit the profile, so he clicked to edit button.
<img height=600 src="https://hackmd.io/_uploads/rkmu4RNXC.jpg">
- Emre adds some details about him and submits.
<img height=600 src="https://hackmd.io/_uploads/HkUq40Nm0.jpg">
- Emre finally sees his new profile.
<img height=600 src="https://hackmd.io/_uploads/ryqdHANm0.jpg">
#### Scenario 2
- Mücahit is already logged in.
- Mücahit wants to search some posts related to the enemies of its favorite comic character. He chooses over categories in the search page.
<img height=600 src="https://hackmd.io/_uploads/SJdPOkHXR.jpg">
- Mücahit writes his favorite character to the search bar and looks for suggestions.
<img height=600 src="https://hackmd.io/_uploads/B1TFdyrmA.jpg">
- Mücahit gets the search results about the enemies.
<img height=600 src="https://hackmd.io/_uploads/SJy6uJHmC.jpg">
#### Scenario 3
- Ozan has already logged in.
- Ozan wants to share his ideas, so he creates a new post.
<img height=600 src="https://hackmd.io/_uploads/SJPOtANX0.jpg">
- Ozan fills the contents and add a tag by using the given suggestions.
<img height=600 src="https://hackmd.io/_uploads/Hk7oYCNmR.jpg">
- Ozan submits the post and tries to find some metadata for his post. He enters the search bar and searches by occupation.
<img height=600 src="https://hackmd.io/_uploads/HJ0rG1BmR.jpg">
- Ozan finds his post, sees the Wikidata information and likes and bookmarks his own post.
<img height=600 src="https://hackmd.io/_uploads/Hy3EmJrXC.jpg">
- Ozan then wants to look who liked his post. However, the post is newly he is the only one who liked the post.
<img height=600 src="https://hackmd.io/_uploads/H1aGUJB7A.jpg">
#### Scenario 4
- Hasan has already logged in.
- He wants to see posts about superheros that are also detectives.
- He selects the occupation category and searches for detective occupation.
- He sees the posts that are related to superheroes that are detectives.
<img height=600 src="https://hackmd.io/_uploads/r1s1iySXR.jpg">
- He learns that a superhero called Batman is a detective. As Hasan has detective curiosity, he wants to learn Batman's real name and where he was born. So, he enters the post.
<img height=600 src="https://hackmd.io/_uploads/Bkbi61B7R.jpg">
- He learns Batman's real name and his birth place.
- He wants to see the post owner's profile. Clicks the owner on up-left.
<img height=600 src="https://hackmd.io/_uploads/SJZ7yeSXA.jpg">
#### Scenario 5 (Web)
- Hasan wants to test this app so he registers to the app using tester2024 as username and password from the web.
<img src="https://hackmd.io/_uploads/HJfiaFLXC.png">
- Then he logs in using his credentials.
<img src="https://hackmd.io/_uploads/SyMkAKUXA.png">
- He can see his feed.
<img src="https://hackmd.io/_uploads/HJwjzevXR.png">
#### Scenario 6 (Web)
- Emre logs in to the app using his credentials (tenacke as username and password).
<img src="https://hackmd.io/_uploads/ryZqhtUQR.png">
- He can see his feed.
<img src="https://hackmd.io/_uploads/rJXBat8QA.png">
#### Links
- <b>Release Tag</b>: Please follow the link to [Group11-Practice-App-Release-v0.2](https://github.com/bounswe/bounswe2024group11/releases/tag/Group11-Practice-App-Release-v0.2).
- <b>Web Application</b>: Please follow the link to [Zenith Web Application](http://164.90.189.150).
- <b>Mobile Application</b>: Download for APK is available under our release tag, please follow the link to [Zenith Mobile Application](https://github.com/bounswe/bounswe2024group11/releases/tag/Group11-Practice-App-Release-v0.2).
- [Project Github Repository](https://github.com/bounswe/bounswe2024group11/)
- [Backend Code of the Project](https://github.com/bounswe/bounswe2024group11/tree/main/backend)
- [Frontend/Web Code of the Project](https://github.com/bounswe/bounswe2024group11/tree/main/web)
- [Mobile Code of the Project](https://github.com/bounswe/bounswe2024group11/tree/main/mobile)
- [Swagger for API Documentation](http://164.90.189.150/api/swagger/)
**Requirements**
- [✅ Software Requirements Specification](https://github.com/bounswe/bounswe2024group11/wiki/Requirements)
**Designs**
- [✅ Class Diagram](https://github.com/bounswe/bounswe2024group11/wiki/Class-Diagrams)
- [✅ Use Case Diagram](https://github.com/bounswe/bounswe2024group11/wiki/Use-Case-Diagrams)
- [✅ Sequence Diagram](https://github.com/bounswe/bounswe2024group11/wiki/Sequence-Diagrams)
**Project Plan**
- [✅ Project Plan](https://github.com/bounswe/bounswe2024group11/wiki/Project-Plan)
- [✅ Responsibility Assignment Matrix (RAM)](https://github.com/bounswe/bounswe2024group11/wiki/Responsibility-Assignment-Matrix)
#### Significant Meeting Notes
<!-- Added a small explanation why the corresponding meeting is important. We may delete them. -->
- [Backend Meeting #6](https://github.com/bounswe/bounswe2024group11/wiki/Backend-Meeting-%236) : Discussion of further work to do on backend.
- [Weekly Sync #16](https://github.com/bounswe/bounswe2024group11/wiki/Weekly-Sync-%2316) : Sync between frontend and backend.
- [Mobile Meeting #2](https://github.com/bounswe/bounswe2024group11/wiki/Mobile-Meeting-%232) : Distribution of tasks in mobile part.
- [Backend Meeting #7](https://github.com/bounswe/bounswe2024group11/wiki/Backend-Meeting-%237) : Distribution of endpoint implementation and their tests.
#### Instruction for Building & Deployment
- You can refer to the detailed guide in [README](https://github.com/bounswe/bounswe2024group11/blob/main/README.md) file in the project repository for deploying and testing the application on your local environment or another host machine.
#### Information Related to Usage
- Do not use the mobile application in dark mode. The components in mobile side are rendered with respect to light mode of Android. Some additional libraries used in this project may be sensitive to the theme changes and may cause render complications. Some icons may not be seen and user experience may be terrible.
- You can use the test user `@ozankrk`.
```bash=
username : ozankrk
password : ozibaba
```
#### Challenges
- Time management was one of the most difficult challenges. Since most of the team members had no experience on software development, learning and implementing take a lot of time. However, we attend classes and also have other responsibilites, we could not get to the end of the project.
- There was no one experienced on the backend team. On top of that, they started to implement the app, without learning core concepts of Django REST Framework. To mitigate this, one of them prepared tutorials on Django REST Framework and relationships of its components and presented to the team.
- Since team members lacked theoretical information about Django REST, they were unable to build on top of the project that was built before Milestone 2. Therefore, they trashed it and started from the start.
- Building a solip API that contains the essential info needed by frontend team was hard as well.
#### Lessons Learned
- Before implementation, learn the core concepts of the programming language/framework.
- Trashing what is already done could be a reasonable decision sometimes and sometimes not. If the milestone is close, the latter may be true.
- Most of the time, time management will be a problem. Try to foresee what should be done at what time and plan accordingly.
- As per backend part, first document the API that is to be built. Then write unit tests for that API. Thirdly, implement the API. Lastly, make further adjustments on the API. This helps to build a more collaborative development with the frontend team since they can develop their codes more time efficient. Otherwise, the two teams would have to continuously communicate and waste time during the integration of the backend to the frontend.
- We should respect our UI designs to see what are the requirements on the web and mobile parts of the application.
#### Reflections
- We can reflect the opinion that project planning and being loyal to the project plan during whole development process is the key for developing a comprehensive good work instead of using the power of the customer deadlines.
- Our communication inside the team was one of our strengths. Even if we are divided into three teams as backend, frontend and mobile, we should have kept communication inside the team during our implementation process. Of course, the lack of communication compared to before milestone was natural due to time-pressure that all three teams faced during the Milestone 3 preparation.
## 2. Contributions
- You can view each team member's biographies & personal efforts page [here](https://github.com/bounswe/bounswe2024group11/wiki#-contributors).
<br />
### Muhammed Emin Arayıcı
<br />
### Yunus Kağan Aydın
#### 3 Important Issues
- Identify the [non-functional requirements](https://github.com/bounswe/bounswe2024group11/wiki/Requirements#-2-non-functional-requirements). [issue](https://github.com/bounswe/bounswe2024group11/issues/61)
- This issue contains the identification of non-functional requirements in our Zenith app. I didn't have any idea on what non-functional requirements could be. I did a research on other applications. I tried to keep it simple and understandable as possible. I communicated with my teammates Mücahit and Emre to reach the final form of non-functional requirements.
- Connect the backend to hosted database. [issue](https://github.com/bounswe/bounswe2024group11/issues/261)
- This issue contains the work on connecting the backend to hosted database. In our app, we tried to keep the security at its maximized level. In order to reach this goal we used [1password](https://1password.com/). With this website, we shared our database info in a secured way. By changing the databases section in settings.py of our app's django folder, we connected the backend with our database. I communicated with Muhammed Emin Arayıcı in this issue. He helped me a lot to get a knowledge on database interconnection.
- Implement proper response codes on endpoints. [issue](https://github.com/bounswe/bounswe2024group11/issues/274)
- This issue contains the work on modifying the default response codes on signup and login mechanisms in our app. Our mechanism were returning response code as 404 when we weren't doing login correctly and 500 when we weren't doing signup correctly. I researched the response code in order to apply this in our API. We had `get_object_or_404` previously. We had to change each of it with another proper response code. This issue helped me to have an idea on the specifications on response codes. I communicated with my teammate Mücahit when I was dealing with this issue. We changed the API structure and wrote the unit test.
#### 3 Important PRs
- feat: connect backend to hosted MySQL server. [PR](https://github.com/bounswe/bounswe2024group11/pull/221)
- This PR contains the work of connecting backend to hosted database. With its merge, backend was connected to hosted database properly and in a secured way. I communicated with Muhammed Emin Arayıcı on understanding the behavior.
- feat(backend): send proper respond status codes. [PR](https://github.com/bounswe/bounswe2024group11/pull/279)
- This PR contains the work of modifying the response codes to proper ones. I communicated with Mücahit Erdoğan Ünlü on implementing new API endpoints. and writing new unit tests.
- fix(backend): add authorization rules and unique constraints for like, bookmark and follow endpoints. [PR](https://github.com/bounswe/bounswe2024group11/pull/387)
- This PR contains the work of adding authorization rules and unique constraints for like, bookmark and follow endpoints. With this PR, multiple like, bookmark on a same post and multiple follow to a same user is prevented. I communicated with Muhammed Emin Arayıcı on implementing this precautions.
#### Wiki Documentations
- Meeting Notes:
- I documented the Weekly Sync [#3](https://github.com/bounswe/bounswe2024group11/wiki/Meeting-%233), [#4](https://github.com/bounswe/bounswe2024group11/wiki/Meeting-%234), [#5](https://github.com/bounswe/bounswe2024group11/wiki/Meeting-%235), [#7](https://github.com/bounswe/bounswe2024group11/wiki/Meeting-%237), [#8](https://github.com/bounswe/bounswe2024group11/wiki/Meeting-%238), [#10](https://github.com/bounswe/bounswe2024group11/wiki/Weekly-Sync-%2310), [#12](https://github.com/bounswe/bounswe2024group11/wiki/Weekly-Sync-%2312), [#13](https://github.com/bounswe/bounswe2024group11/wiki/Weekly-Sync-%2313), [#14](https://github.com/bounswe/bounswe2024group11/wiki/Weekly-Sync-%2314), [#15](https://github.com/bounswe/bounswe2024group11/wiki/Weekly-Sync-%2315), [#16](https://github.com/bounswe/bounswe2024group11/wiki/Weekly-Sync-%2316).
- I documented the Backend Meeting [#1](https://github.com/bounswe/bounswe2024group11/wiki/Backend-Meeting-%231), [#2](https://github.com/bounswe/bounswe2024group11/wiki/Backend-Meeting-%232), [#3](https://github.com/bounswe/bounswe2024group11/wiki/Backend-Meeting-%233), [#4](https://github.com/bounswe/bounswe2024group11/wiki/Backend-Meeting-%234), [#5](https://github.com/bounswe/bounswe2024group11/wiki/Backend-Meeting-%235).
- Requirements:
- I documented the [non-functional requirements](https://github.com/bounswe/bounswe2024group11/wiki/Requirements#-2-non-functional-requirements).
- How to Connect Django to MySQL
- I wrote a simple [document](https://github.com/bounswe/bounswe2024group11/wiki/How-to-Connect-Django-to-MySQL) on how to connect Django to MySQL.
- Well Designed Documented API
- We wrote a [document](https://github.com/bounswe/bounswe2024group11/wiki/Well-Designed-Documented-API's) that consists of the criterias on how to write a well designed documented API with Ceydanur Şen. Then I [trimmed](https://github.com/bounswe/bounswe2024group11/issues/262) the excessed parts.
- Open API Specifications as in Swagger UI
- I wrote a [document](https://github.com/bounswe/bounswe2024group11/wiki/Open-API-Specifications-as-in-Swagger-UI) on the basic Open API specifications as in Swagger UI which we used in order to implement our API's.
- How to Store Image Fields
- I wrote a [document](https://github.com/bounswe/bounswe2024group11/wiki/How-to-Store-Image-Fields) on how to store image fields in our app. But we preferred the way of adding URL's. So this documentation was never used.
#### Description of API Functions Implemented
- I have implemented viewSet definitions of like, bookmark and follow with Muhammed Emin Arayıcı. This viewSet's were compatible with [functional requirements](https://github.com/bounswe/bounswe2024group11/wiki/Requirements#-1-functional-requirements) which was written by Emre Kılıç and Mücahit Erdoğan Ünlü.
```
class LikeViewSet(viewsets.ModelViewSet):
queryset = Like.objects.all()
serializer_class = LikeSerializer
permission_classes = [permissions.IsAuthenticated, IsUserOwnerOrReadOnly]
def perform_create(self, serializer):
serializer.save(user=self.request.user)
class BookmarkViewSet(viewsets.ModelViewSet):
queryset = Bookmark.objects.all()
serializer_class = BookmarkSerializer
permission_classes = [permissions.IsAuthenticated, IsUserOwnerOrReadOnly]
def perform_create(self, serializer):
serializer.save(user=self.request.user)
class FollowViewSet(viewsets.ModelViewSet):
queryset = Follow.objects.all()
serializer_class = FollowSerializer
permission_classes = [permissions.IsAuthenticated, IsFollowerOwnerOrReadOnly]
def get_object(self):
queryset = self.get_queryset()
obj = get_object_or_404(queryset, follower=self.request.user, following__id=self.kwargs['pk'])
return obj
def destroy(self, request, *args, **kwargs):
follow = self.get_object()
if follow.follower != request.user:
return Response(status=status.HTTP_403_FORBIDDEN)
else:
self.perform_destroy(follow)
return Response(status=status.HTTP_204_NO_CONTENT)
def perform_create(self, serializer):
serializer.save(follower=self.request.user)
```
- Those view sets are connected to these endpoints:
```
router.register(r"likes", LikeViewSet)
router.register(r"bookmarks", BookmarkViewSet)
router.register(r"follows", FollowViewSet)
```
- We used permissions in order to control the authorization on multiple liking, bookmarking on a single post and multiple following on a single user.
```
class IsAuthorOwnerOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
return True
return obj.author == request.user
class IsUserOwnerOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
return True
return obj.user == request.user
class IsFollowerOwnerOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
return True
return obj.follower == request.user
class IsProfileOwnerOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
return True
return obj.owner == request.user
```
#### Description of Unit Tests
- These functions were tested manually. So we didn't need a unit test.
#### Challenges Faced During the Implementation and Their Solutions
- I didn't have any experience on working as a team in a software development project. Getting to know each members and their strengths and weaknesses was a field that I wasn't experienced on. But when 10 people gather in a positive attitude to make things happen, walls will fall down. Each member of our team had the great disipline to accomplish their tasks. Sometimes we slept shorter hours, couldn't pay attention to other classes efficiently and so on. But we learned what does it take to become a valuable team member.
- Developing in backend was a new subject for me because I didn't have any experience on backend developing. I have always suspected this area of being more boring and sophisticated when comparing with mobile and web developing. But it turned out that backend developing was really not that horrible as it looked. I truly believe that I gained valuable experience on backend developing. I may follow the paths of being a backend developer in the future.
<br />
### Muhammet Emin Çiftçi
#### 3 Important Issues
#### 3 Important Pull Requests
#### Wiki Documentations
<br />
### Ümit Can Evleksiz
#### 3 Important Issues
#### 3 Important Pull Requests
#### Wiki Documentations
<br />
### Ozan Oytun Karakaya
#### 3 Important Issues
- [Updating UML Diagrams](https://github.com/bounswe/bounswe2024group11/issues/284): This issue covers the updating process of all UML Diagrams that I have completed with [Hasan Kerem Şeker](https://github.com/bounswe/bounswe2024group11/wiki/Hasan-Kerem-%C5%9Eeker) and [Mücahit Erdoğan Ünlü](https://github.com/bounswe/bounswe2024group11/wiki/M%C3%BCcahit-Erdo%C4%9Fan-%C3%9Cnl%C3%BC) before the implementation phase. Beforehand, I was mainly responsible for creating the [Use-Case UML Diagram](https://github.com/bounswe/bounswe2024group11/wiki/Use-Case-Diagrams) & [Search Post UML Sequence Diagram](https://github.com/bounswe/bounswe2024group11/wiki/Sequence-Diagrams#search-post) with [Muhammed Emin Arayıcı](https://github.com/bounswe/bounswe2024group11/wiki/Muhammed-Emin-Aray%C4%B1c%C4%B1).
- [Dockerization & Deployment of Web Application](https://github.com/bounswe/bounswe2024group11/issues/306): This issue covers the deployment process of the web application. We created separate issues for deployment of each service in our server. There are two more issues highly related to this issue: [Database Service Deployment](https://github.com/bounswe/bounswe2024group11/issues/285) and [Backend Service Deployment](https://github.com/bounswe/bounswe2024group11/issues/218). All processes related to Dockerization & Deployment of our application is completed by [Muhammed Emin Arayıcı](https://github.com/bounswe/bounswe2024group11/wiki/Muhammed-Emin-Aray%C4%B1c%C4%B1) and me.
- [Update Profile Endpoint](https://github.com/bounswe/bounswe2024group11/issues/447): This issue covers the development process of `api/v2/profiles/` endpoint. It is important to note that this issue is highly related to [previous issue](https://github.com/bounswe/bounswe2024group11/issues/437) about the work I have completed on same endpoint.
#### 3 Important Pull Requests
- [Profile Endpoint Features & Follow Endpoint Fixes](https://github.com/bounswe/bounswe2024group11/pull/450): This PR covers the work done on the `/api/v2/profiles/` & `/api/v2/follows/` endpoints. It is important to note that this PR follows the work done on the previous [PR](https://github.com/bounswe/bounswe2024group11/pull/446) about `/api/v2/profiles/`, thus these two PR covers all the work I have completed about these two endpoints.
- [Dockerize & Deploy Whole Application](https://github.com/bounswe/bounswe2024group11/pull/296): This PR covers the work I have completed with [Muhammed Emin Arayıcı](https://github.com/bounswe/bounswe2024group11/wiki/Muhammed-Emin-Aray%C4%B1c%C4%B1) about the whole deployment process of our application.
- [Post Endpoint Features](https://github.com/bounswe/bounswe2024group11/pull/381): This PR covers the work I have completed about PATCH & DELETE HTTP Requests to `/api/v2/posts/` endpoint.
#### Wiki Documentations
- I haven't prepared any wiki documentation for describing my contributions, however, I have prepared a [README file](https://github.com/bounswe/bounswe2024group11/blob/Group11-Practice-App-Release-v0.2/README.md) for root directory of our repository which describes the steps of the deployment of the application for building and running the application.
#### Description of API Functions Implemented
I have contributed to the implementation of the 3 main endpoints which play significant role on the functionality of the backend service.
##### PATCH & DELETE Requests to `/api/v2/posts/`
- This endpoint is used to get followed users shared posts and posts of the user herself/himself. Also by providing a POST request to this endpoint, users are able to create posts. I have contributed mainly to the part of updating & deleting a post by providing the post id.
- Following steps demonstrate an example of updating and deleting a post sequentially.
- I have created a sample post, `post_id: 19`, beforehand for testing with my user `@ozankrk` which is accesible with the get command.
```bash
curl -X GET http://164.90.189.150/api/v2/posts/19/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzE2MTI5NjcwLCJpYXQiOjE3MTYwNDMyNzAsImp0aSI6IjRhNTNlZTNkZjU0YjRkOWZhM2VkYTcwNmJkZDljMmE2IiwidXNlcl9pZCI6NX0.myaRt08-TUQgYv0xHe70cOrWeokMfRixq0qM113wbTE"
```
- Below, you can see the response of this api call. All related information about the post itself such as the likes, profile of the author or following information and so on, is returned for possible actions can be taken by the user in the client-side.
```bash
{
"id":19,
"author_profile":{"id":5,"username":"ozankrk","email":"ozan@gmail.com","fullname":"Ozan Oytun","picture":"https://i.ibb.co/kHBtv0g/zenith.png","biography":"Interested in marvel"},
"like_count":0,
"bookmark_count":0,
"liked_by":[],
"is_liked":false,
"is_bookmarked":false,
"is_following":true,
"title":"sample post",
"content":"this is the content of the sample post",
"image_src":null,
"qid":null,
"qtitle":null,
"created_at":"2024-05-18T14:50:31.904047Z",
"updated_at":"2024-05-18T14:50:31.904114Z",
"author":5
}
```
- Below, you can see the command for updating this post.
```bash
curl -X PATCH http://164.90.189.150/api/v2/posts/19/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzE2MTI5NjcwLCJpYXQiOjE3MTYwNDMyNzAsImp0aSI6IjRhNTNlZTNkZjU0YjRkOWZhM2VkYTcwNmJkZDljMmE2IiwidXNlcl9pZCI6NX0.myaRt08-TUQgYv0xHe70cOrWeokMfRixq0qM113wbTE"
-d '{"content" : "this is the updated content of the sample post"}'
```
- Below, you can see the response of this api call. Please note that the `content` field is now updated as wished.
```bash
{
"id":19,
"author_profile":{"id":5,"username":"ozankrk","email":"ozan@gmail.com","fullname":"Ozan Oytun","picture":"https://i.ibb.co/kHBtv0g/zenith.png","biography":"Interested in marvel"},
"like_count":0,
"bookmark_count":0,
"liked_by":[],
"is_liked":false,
"is_bookmarked":false,
"is_following":true,
"title":"sample post",
"content":"this is the updated content of the sample post",
"image_src":null,
"qid":null,
"qtitle":null,
"created_at":"2024-05-18T14:50:31.904047Z",
"updated_at":"2024-05-18T14:50:31.904114Z",
"author":5
}
```
- Below, you can see the command for deleting this post.
```bash
curl -X DELETE http://164.90.189.150/api/v2/posts/19/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzE2MTI5NjcwLCJpYXQiOjE3MTYwNDMyNzAsImp0aSI6IjRhNTNlZTNkZjU0YjRkOWZhM2VkYTcwNmJkZDljMmE2IiwidXNlcl9pZCI6NX0.myaRt08-TUQgYv0xHe70cOrWeokMfRixq0qM113wbTE"
```
- The response of this api call is a successful deletion message with HTTP Code 204. If this api call is made with another user's token, which is not authorized for my user, response is a simple not authorized message with HTTP Code 403.
- I am well aware of the fact that this is not the most secure way demonstrating the execution :), especially providing the token of my user. However, this is best way of demonstrating the workflow of the endpoint.
##### Implementation of `/api/v2/profiles/`
- I have created all parts of this endpoint with the help of [Ceydanur Şen](https://github.com/bounswe/bounswe2024group11/wiki/Ceydanur-%C5%9Een). A profile for user is created at the moment of registration of a user. I will demonstrate the PATCH request to update any field of a my user's profile.
- Below, you can see the command for getting the user, with `user_id: 5`.
```bash
curl -X GET http://164.90.189.150/api/v2/profiles/5/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzE2MTI5NjcwLCJpYXQiOjE3MTYwNDMyNzAsImp0aSI6IjRhNTNlZTNkZjU0YjRkOWZhM2VkYTcwNmJkZDljMmE2IiwidXNlcl9pZCI6NX0.myaRt08-TUQgYv0xHe70cOrWeokMfRixq0qM113wbTE"
```
- Below, you can see the response of this api call. All user related information in the profile page is returned since all of the returned values are, at least as designed, used in the frontend/mobile side for displaying in the profile page. Also, please note that all users have their `profile_id` equal to their `user_id`.
```bash
{
"id":5,
"is_following":true,
"posts":[{"id":11,"username":"ozankrk","user_id":"5","like_count":0,"bookmark_count":0,"liked_by":[],"is_liked":false,"is_bookmarked":false,"is_following":true,"title":"The death of an era","content":"Here is why you should not rely on a single ... The most comprehensive approach","image_src":"https://static.wikia.nocookie.net/marveldatabase/images/e/e1/The_Marvel_Universe.png/revision/latest?cb=20110513164401","qid":null,"qtitle":null,"created_at":"2024-05-17T07:13:57.443922Z","updated_at":"2024-05-17T07:13:57.443965Z"},{"id":13,"username":"ozankrk","user_id":"5","like_count":1,"bookmark_count":1,"liked_by":["ozankrk"],"is_liked":true,"is_bookmarked":true,"is_following":true,"title":"Hawkeye","content":"Good archer","image_src":"","qid":"Q19095","qtitle":"Hawkeye","created_at":"2024-05-17T08:06:08.511891Z","updated_at":"2024-05-17T08:06:08.511941Z"},{"id":15,"username":"ozankrk","user_id":"5","like_count":2,"bookmark_count":1,"liked_by":["ozankrk","Tatü"],"is_liked":true,"is_bookmarked":true,"is_following":true,"title":"The Genius Behind The Armor","content":"Let's chat about Iron Man! Tony Stark, the genius billionaire playboy philanthropist, is behind the iconic suit. His tech innovations and battles are legendary. What's your favorite Iron Man moment or suit?","image_src":"https://images.unsplash.com/photo-1635863138275-d9b33299680b?q=80&w=3731&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D","qid":"Q180704","qtitle":"Iron Man","created_at":"2024-05-17T12:05:10.820919Z","updated_at":"2024-05-17T12:05:10.820974Z"},{"id":19,"username":"ozankrk","user_id":"5","like_count":0,"bookmark_count":0,"liked_by":[],"is_liked":false,"is_bookmarked":false,"is_following":true,"title":"sample post","content":"this is the content of the sample post","image_src":null,"qid":null,"qtitle":null,"created_at":"2024-05-18T14:50:31.904047Z","updated_at":"2024-05-18T14:50:31.904114Z"}],
"followers":["ozankrk","memin41"],
"followings":["emre","hyildirim","ozankrk","memin41","hyildirim2","johnnyS","umit","jackk","A"],
"follower_count":2,
"following_count":9,
"post_count":4,
"picture":"https://i.ibb.co/kHBtv0g/zenith.png",
"biography":"Interested in marvel",
"owner":5
}
```
- Below, you can see the command for updating the user profile. The biography field is updated in this sample call.
```bash
curl -X PATCH http://164.90.189.150/api/v2/profiles/5/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzE2MTI5NjcwLCJpYXQiOjE3MTYwNDMyNzAsImp0aSI6IjRhNTNlZTNkZjU0YjRkOWZhM2VkYTcwNmJkZDljMmE2IiwidXNlcl9pZCI6NX0.myaRt08-TUQgYv0xHe70cOrWeokMfRixq0qM113wbTE" \
-d '{"biography" : "I am currently interested in DC"}'
```
- Below, you can see the response of this api call. Please note that biography field is now updated as wished.
```bash
{
"id":5,
"is_following":true,
"posts":[{"id":11,"username":"ozankrk","user_id":"5","like_count":0,"bookmark_count":0,"liked_by":[],"is_liked":false,"is_bookmarked":false,"is_following":true,"title":"The death of an era","content":"Here is why you should not rely on a single ... The most comprehensive approach","image_src":"https://static.wikia.nocookie.net/marveldatabase/images/e/e1/The_Marvel_Universe.png/revision/latest?cb=20110513164401","qid":null,"qtitle":null,"created_at":"2024-05-17T07:13:57.443922Z","updated_at":"2024-05-17T07:13:57.443965Z"},{"id":13,"username":"ozankrk","user_id":"5","like_count":1,"bookmark_count":1,"liked_by":["ozankrk"],"is_liked":true,"is_bookmarked":true,"is_following":true,"title":"Hawkeye","content":"Good archer","image_src":"","qid":"Q19095","qtitle":"Hawkeye","created_at":"2024-05-17T08:06:08.511891Z","updated_at":"2024-05-17T08:06:08.511941Z"},{"id":15,"username":"ozankrk","user_id":"5","like_count":2,"bookmark_count":1,"liked_by":["ozankrk","Tatü"],"is_liked":true,"is_bookmarked":true,"is_following":true,"title":"The Genius Behind The Armor","content":"Let's chat about Iron Man! Tony Stark, the genius billionaire playboy philanthropist, is behind the iconic suit. His tech innovations and battles are legendary. What's your favorite Iron Man moment or suit?","image_src":"https://images.unsplash.com/photo-1635863138275-d9b33299680b?q=80&w=3731&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D","qid":"Q180704","qtitle":"Iron Man","created_at":"2024-05-17T12:05:10.820919Z","updated_at":"2024-05-17T12:05:10.820974Z"},{"id":19,"username":"ozankrk","user_id":"5","like_count":0,"bookmark_count":0,"liked_by":[],"is_liked":false,"is_bookmarked":false,"is_following":true,"title":"sample post","content":"this is the content of the sample post","image_src":null,"qid":null,"qtitle":null,"created_at":"2024-05-18T14:50:31.904047Z","updated_at":"2024-05-18T14:50:31.904114Z"}],
"followers":["ozankrk","memin41"],
"followings":["emre","hyildirim","ozankrk","memin41","hyildirim2","johnnyS","umit","jackk","A"],
"follower_count":2,
"following_count":9,
"post_count":4,
"picture":"https://i.ibb.co/kHBtv0g/zenith.png",
"biography":"I am currently interested in DC",
"owner":5
}
```
##### Modification of HTTP Requests to `/api/v2/follows/`
- I have updated this endpoint so that all HTTP requests can be made by providing the `user_id` in the URL so that front-end and mobile side can use this endpoint inside posts and profiles to control follow operations.
- Below, you can see an example of getting an information whether my user, `@ozankrk`, is following the user with `user_id: 3`.
```bash
curl -X GET http://164.90.189.150/api/v2/follows/3/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzE2MTI5NjcwLCJpYXQiOjE3MTYwNDMyNzAsImp0aSI6IjRhNTNlZTNkZjU0YjRkOWZhM2VkYTcwNmJkZDljMmE2IiwidXNlcl9pZCI6NX0.myaRt08-TUQgYv0xHe70cOrWeokMfRixq0qM113wbTE"
```
- Below, you can see the response for this call. `id` field shows the id of follow object. `follower` and `following` fields shows the ids of the follower user and the user that he/she follows.
```bash
{
"id":1,
"follower_username":"ozankrk",
"following_username":"emre",
"created_at":"2024-05-17T06:54:49.574006Z",
"follower":5,
"following":3
}
```
- Other HTTP requests can be done just as above by just modifying the request parameter of `$curl` command. Please don't forget the changing the `user_id` in the URL for necessary action related to specific user.
#### Description of Unit Tests
- Here, you can find the unit test I have written for testing the endpoint for posts. Please note that this test is not pushed to the repository, since I have used this test only on my local development environment.
- The test file below should be put into /backend/core/tests folder for testing with name `test_posts.py` (recommended) and in order to run all test, simply run the command below.
```bash=
cd bounswe2024group11/backend
python manage.py test
```
- Code for this unit test is attached below.
```python
from rest_framework.test import APITestCase, APIClient
from rest_framework import status
from django.urls import reverse
from django.contrib.auth.models import User
from core.models import Post
class PostTests(APITestCase):
def setUp(self):
self.client = APIClient()
self.user = User.objects.create_user(username="testuser_post", password="testpassword_post")
self.client.force_authenticate(user=self.user)
self.post = Post.objects.create(author=self.user, title="Test Post", content="Test Content")
def test_get_post(self):
response = self.client.get(reverse('post-detail', kwargs={"pk": self.post.pk}))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["title"], self.post.title)
self.assertEqual(response.data["content"], self.post.content)
self.assertEqual(response.data["author"], self.user.id)
def test_update_post(self):
data = {"content": "Updated Content"}
response = self.client.patch(reverse('post-detail', kwargs={"pk": self.post.pk}), data, format="json")
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["content"], data["content"])
def test_delete_post(self):
response = self.client.delete(reverse('post-detail', kwargs={"pk": self.post.pk}))
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
```
#### Other Significant Work
- I have created a reverse-proxy structure in our deployment server so that our endpoints can be accessible without providing a port number. NGINX configuration is added in front of the whole service structure so that calls with starting with `/api` is directed to backend service whereas clients are directed to front-end service otherwise. You can access to the [issue](https://github.com/bounswe/bounswe2024group11/issues/359) and the [pull request](https://github.com/bounswe/bounswe2024group11/pull/362) of this contribution here.
- CORS related errors were constantly faced at the frontend development side. I have made necessary configurations for CORS allowed hosts in the `config/settings.py` file at the `/backend` directory with the help of [Muhammed Emin Arayıcı](https://github.com/bounswe/bounswe2024group11/wiki/Muhammed-Emin-Aray%C4%B1c%C4%B1). You can access to the [issue](https://github.com/bounswe/bounswe2024group11/issues/323) and the [pull request](https://github.com/bounswe/bounswe2024group11/pull/324) of this contribution here.
#### Challenges Faced
- Backend related development was an area that I have been mostly avoiding of before this course, since I was not interested in this area of Computer Engineering. I was going through an hardship of creating views since it was kind of hard for me to understand the Django Framework's structure caused by my lack of experience. By the time, with the help of my teammates and documentations & forums about the framework, I got used to write code for backend side.
- Docker is an application makes running remote servers super efficiently, however, it hides most of the processes it runs behind the scenes due to transparency policy of the application. Thus, errors we have faced with [Muhammed Emin Arayıcı](https://github.com/bounswe/bounswe2024group11/wiki/Muhammed-Emin-Aray%C4%B1c%C4%B1) during the deployment process took our time to overcome. We have searched through web and got the help of LLMs such as ChatGPT, also we have watched lots of tutorials, to understand the structure of Docker which leaded us to solutions of our problems in the deployment.
- Another challenge I have faced was the communication issues with my teammates which I was not expecting to face. I think, most of team members tried to make contributions in order to finish our milestone completely due to time pressure the team faced. However, at some points, we couldn't manage to populate team's efforts, at the backend side, in a cumulative manner at some point which made us lose relatively large amount of time.
- Lastly, the fact that this course's grades are given individually makes people to focus on their contributions only, sometimes, instead of putting a team work which leads to inefficient situations in case of team working.
- Personally, I want to thank to my teammate [Muhammed Emin Arayıcı](https://github.com/bounswe/bounswe2024group11/wiki/Muhammed-Emin-Aray%C4%B1c%C4%B1) who helped me overcoming most of the challenges I have faced.
<br />
### Emre Kılıç
#### 3 Important Issues
- Identify User Requirements [#69](https://github.com/bounswe/bounswe2024group11/issues/69):
- This issue covers all details in user requirements. In this issue, I have identified the user requirements by reading the project description, assessing the answers which we have asked in customer meeting and following the requirement specification practices.
- Class Diagrams [#149](https://github.com/bounswe/bounswe2024group11/issues/149):
- This issue covers the improvements to a prototype class diagram using the requirements. In this issue, Hasan Kerem and I assessed the first version of the class diagram and identified the missing details. We come up with some solutions to Search and Post and drew the improved class diagram using the mermaid library in GitHub Markdown.
- Build the Mobile App [#333](https://github.com/bounswe/bounswe2024group11/issues/333):
- This issue covers the building and deployment of the mobile application. The implemented mobile app had been tested on emulators before releases. Taking the build requires testing of the application using real mobile phones and solving building related problems. With Muhammed Emin Arayıcı, we have managed to solve all bugs related to production build and prepare our app to the release.
#### 3 Important Pull Requests
- feat(mobile): added token to user context and api calls [#379](https://github.com/bounswe/bounswe2024group11/pull/379):
- This pull request covers the modifications of all API calls and session control. After the backend system had changed, the HTTP requests and session control mechanisms had to change. In this pull request, the user context which stores session related user data is modified and the access token based system is added in the HTTP request library that we implemented. This token is stored in the context.
- feat(backend): add login endpoint with swagger, bruno and unit tests [#407](https://github.com/bounswe/bounswe2024group11/pull/407):
- This pull request covers all details of developing the login enpoint with implementation, testing and documentation. I have implemented the login endpoint which is described below in the API description part. I also have added the unit tests and swagger documentations of that endpoint in the same pull request.
- feat(mobile): connect to backend [#431](https://github.com/bounswe/bounswe2024group11/pull/431):
- This pull request covers all details in implementing new API call functions and editing the old calls. Our backend has been changed due to some implementation choices and eases of the new solution. This change causes new problems for mobile application in terms of connecting these two parts. Muhammed Emin Arayıcı and Yunus Kağan Aydın, two participants of the backend team, helped me to figure out the new API descriptions and solve the new issues.
#### Wiki Documentations
You can find the documentations I have written in the wiki page across the project. These researches helped us to figure out the nature of semantic browsing and WikiData SPARQL query mechanism. These researches also provides a good and compact information about the searching mechanism of this project. The team then used the general information about semantic search and examples provided in SPARQL documentation to implement the semantic searching of our application. I have contributed to these documents with Hasan Kerem and Ümit Can.
- Semantic Browsers [documentation](https://github.com/bounswe/bounswe2024group11/wiki/Semantic-Search)
- SPARQL [documentation](https://github.com/bounswe/bounswe2024group11/wiki/SPARQL)
#### Description of API
##### Implemetation of `POST` method for `login/`
- I have implemented the `login/` API endpoint of our application. This endpoint gets username and password and handles the authorization process. Thanks to Mücahit, I have learned how to implement an API function. He also helped and reviewed me during this implementation process.
- The API creates the session and sends user data and access tokens to the frontend side. Returns refresh token to refresh the access when the token is expired. Returns access token
- The method of the `login/` endpoint is `POST`. Other types of methods are not accepted in this endpoint.
- This request accepts two body parameters: `username` and `password`. These parameter should not be null.
- The example usage is given as a bash command below:
```bash=
curl -X POST http://164.90.189.150/api/v2/login/ \
-H 'Content-Type: application/json' \
-d '{ "username": "emre", "password": "emre"}'
```
- This HTTP request handles the body and returns 3 different responses:
- Response code `200`
- This response refers to a successful login operation and returns three fields as a result of this login operation. The response of this example successful result is below:
```json
{
"refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTcxNjY2ODUxOSwiaWF0IjoxNzE2MDYzNzE5LCJqdGkiOiJhMWYyMjNlY2U0NWY0YTJiYmI4YmVjYThjYTI2ZjEzZCIsInVzZXJfaWQiOjN9.F32U9JYp3LXAn6gPSOLpZHcrt0Ww9pO1xUWf0ske7nk",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzE2MTUwMTE5LCJpYXQiOjE3MTYwNjM3MTksImp0aSI6IjAwYjU4YmZmOGVmYTQyNGQ5MWI4Y2U3ZDk0NDhiMTFhIiwidXNlcl9pZCI6M30.KRE7j4UqkfDlt87kahSygj6tjcc0PBIFAQwNdZ00RoI",
"user": {
"id":3,
"username": "emre",
"email": "emre@mail.com",
"fullname": "Emre Kilic"
}
}
```
- Response code `400`
- This response refers to a bad request where the request body has some missing details. It returns a single error field corresponding to the error message. A response of an example bad request where the username or password has not been given as a body is below:
```json
{
"error": "Please provide both username and password"
}
```
- Response code `401`
- This response refers to an invalid credentials. This response is generated when a login operation is tried with a non existing username or wrong password. It returns a single error field corresponding to the error message. A response of an example of an invalid request is below:
```json
{
"error": "Invalid credentials"
}
```
- The documentation of this API endpoint is documented using swagger. It is part of the deployment and can be reached through the [swagger page](http://164.90.189.150:8000/api/v2/swagger) of our website. The code snippet of the swagger documentation is below.
```python=
login_swagger = {
"request_body": openapi.Schema(
type=openapi.TYPE_OBJECT,
required=["username", "password"],
properties={
"username": openapi.Schema(
type=openapi.TYPE_STRING, description="The username of the user."
),
"password": openapi.Schema(
type=openapi.TYPE_STRING, description="The password of the user."
),
},
),
"responses": {
200: openapi.Response(
description="Login successful. Returns the user details and tokens.",
schema=openapi.Schema(
type=openapi.TYPE_OBJECT,
properties={
"refresh": openapi.Schema(
type=openapi.TYPE_STRING,
description="The refresh token for the user.",
),
"token": openapi.Schema(
type=openapi.TYPE_STRING,
description="The access token for the user.",
),
"user": openapi.Schema(
type=openapi.TYPE_OBJECT,
properties={
"id": openapi.Schema(type=openapi.TYPE_INTEGER),
"username": openapi.Schema(type=openapi.TYPE_STRING),
"email": openapi.Schema(type=openapi.TYPE_STRING),
"first_name": openapi.Schema(type=openapi.TYPE_STRING),
"last_name": openapi.Schema(type=openapi.TYPE_STRING),
},
),
},
),
),
400: "Please provide both username and password.",
401: "Invalid credentials.",
},
}
```
#### Description of Unit Tests
- Within the implementation of the `login/` API endpoint, the unit test related to this operation is also implemented. The test script is added to the repository in `test_login.py`. You can run the test using this script after cloning the repository.
```bash=
cd bounswe2024group11/backend
python manage.py test
```
- The unit test is implemented using Django Rest Framework `APITestCase` class. In the testing process, a test user is created with the code snippet below.
```python=
def setUp(self):
self.url = reverse("login")
self.username = "testuser"
self.password = "testpassword"
self.user = User.objects.create_user(
username=self.username, password=self.password
)
```
- With this test user, all three possible responses are tested with the code snippets below.
```python=
def test_login_success(self):
data = {"username": self.username, "password": self.password}
response = self.client.post(self.url, data, format="json")
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn("refresh", response.data)
self.assertIn("token", response.data)
self.assertIn("user", response.data)
self.assertEqual(response.data["user"]["username"], self.username)
def test_login_missing_credentials(self):
data = {"username": self.username}
response = self.client.post(self.url, data, format="json")
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(
response.data["error"], "Please provide both username and password"
)
def test_login_invalid_credentials(self):
data = {"username": self.username, "password": "wrongpassword"}
response = self.client.post(self.url, data, format="json")
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
self.assertEqual(response.data["error"], "Invalid credentials")
```
#### Contributions
- Here you can find my milestone 3 contributions as a table corresponding to its digital footprint.
| Contribution | Footprint |
| ------ | -------- |
| Implemented the screen where users create a post in mobile. This screen can be reached with a button in feed screen. The navigation of this screen is also added to the system by editing the navigation container in home screen. | [#355](https://github.com/bounswe/bounswe2024group11/pull/355) |
| Edited the request library where other components creates HTTP requests. New library functions are added for every HTTP request method that is used throughout the implementation. | [#368](https://github.com/bounswe/bounswe2024group11/pull/368) |
| Implemented a suggestion feature which is used in create post and search. Two main functionalities are with this contribution. A component which renders the suggestions and the HTTP request to handle the information and communication. | [#371](https://github.com/bounswe/bounswe2024group11/pull/371) |
| Modified user context which is used to store the user data and used for session control. After the modifications and improvements in the backend, the API access tokens are added to this user context and login API connection is modified according to support the new features. | [#379](https://github.com/bounswe/bounswe2024group11/pull/379) |
| Implemented the login API endpoint. After discarding the old authentication system in milestone 2, the login API endpoint must be written from scratch with new system. In this contribution, all the details related to login operation is added. Unit tests, API swagger documentations and HTTP responses are implemented. | [#407](https://github.com/bounswe/bounswe2024group11/pull/407) |
#### Challenges Faced
- The biggest challenge of this project was the lack of experience. I have never been part of a software development team. It was challenging to orientate in the group and communicate each other. At first, I tried to be active in every task to ensure that everything works fine. This was good in the first place because of the low workloads of the tasks. It helped me to learn every aspect of the process of designing a software. After the tasks became overwhelming and required some output as a group, We had to find a nice way of dividing the tasks and catch the deadlines. Besides the team experience, I also have never developed a software app from scratch. We had to figure out the way of designing, implementing, testing and deploying the app. I think we have managed to work as a team and finished the project.
- Developing mobile application was a challenging task, too. I have never developed a React Native mobile application. And before that, I have never written javascript. The challenge was learning how the things work in a language which is quite high level. Then I have learned the main functionalities in React API and after that I have managed to learn the React Native.
- Taking production builds was another challenging task. We used Expo tool thinking our DevOps part for the mobile would be easier. But Expo requires that the builds should be taken in the remote server but local system. Using free accounts for server usage was time-consuming and caused some unnecessary procedures. In every build, I had to solve some bugs related to the differences between development server and production builds. After adding necessary Android flags to solve and suppress the errors and took the working build.
- There are some challenges in UI libraries in React Native. Some libraries are still under development and have inner problems. So I had to figure out whether the errors come from us or from the library. Additionaly, some features are not exist in UI libraries so I had to implement them on our own. The suggestion feature is implemented from scratch.
- Connecting to backend was a difficult task. As it is understood easily from the history of pull requests, I had to revise and modify the HTTP requests again and again. Old system required FormData format in HTTP request body and new system required traditional JSON string. I had to change and modify headers and other procedures in order to establish a working connection to backend.
<br />
### Hasan Kerem Şeker
#### 1-Three Most Important Issues
- [Create User Scenarios](https://github.com/bounswe/bounswe2024group11/issues/63)
- [Implement WikiData Search Endpoint](https://github.com/bounswe/bounswe2024group11/issues/424)
- [Create Post Component](https://github.com/bounswe/bounswe2024group11/issues/393)
#### Three Most Important PRs
- [feature(web): implement create post, view post, and post edit delete dropdown ui](https://github.com/bounswe/bounswe2024group11/pull/369)
- [feature(web): implement profile ui](https://github.com/bounswe/bounswe2024group11/pull/358)
- [feat(backend): expose wiki data info endpoint](https://github.com/bounswe/bounswe2024group11/pull/426)
#### Wiki Documentation
- [Semantic Search](https://github.com/bounswe/bounswe2024group11/wiki/Semantic-Search) and its [issue](https://github.com/bounswe/bounswe2024group11/issues/51)
#### Descriptions of Third-party APIs and the API functions Implemented|
- Implemented Wiki Info endpoint (`/v2/info`) with Mücahit Erdoğan Ünlü and Ümit Can Evleksiz. This API allows us to query wikidata using a keyword and return the result to the frontend.
#### Descriptions of Unit Tests
- Implemented tests for Wiki Info view with Mücahit Erdoğan Ünlü and Ümit Can Evleksiz. This test has three cases.
- The first case is querying with a valid qid and this must return valid results having fileds like Inception, Gender, Birth Name', Place of Birth, Image, Description, Label.
- The second case is querying with an invalid qid and this must return an error message 'QID should start with "Q".' and status code 400.
- The third case is querying without a qid and this must return an error message 'Parameter 'qid" is required.' and status code 400.
-
#### Description of Other Significant Work
| Task |
|----------|
| Created five user scenarios([Scenario 1](https://github.com/bounswe/bounswe2024group11/wiki/Scenario-1) [Scenario 2](https://github.com/bounswe/bounswe2024group11/wiki/Scenario-2) [Scenario 3](https://github.com/bounswe/bounswe2024group11/wiki/Scenario-3) [Scenario 4](https://github.com/bounswe/bounswe2024group11/wiki/Scenario-4) [Scenario 5](https://github.com/bounswe/bounswe2024group11/wiki/Scenario-5)) with [Ceydanur Şen](https://github.com/bounswe/bounswe2024group11/wiki/Ceydanur-%C5%9Een)|
| Read React Router documentation to create [Example Routes](https://github.com/bounswe/bounswe2024group11/issues/212) |
| Created the initial version [class diagrams](https://github.com/bounswe/bounswe2024group11/wiki/Class-Diagrams) with [Emre Kılıç](https://github.com/tenacke) and [Mücahit Erdoğan Ünlü](https://github.com/MucahitErdoganUnlu).|
| Created the initial Sequence Diagrams which can be seen from the history tab of the sequence diagrams. It is the oldest version called [Initial Sequence diagram draft](https://github.com/bounswe/bounswe2024group11/wiki/Sequence-Diagrams/b5dc8dd900208142ead94c0a949eeaeb06758976) |
| Bootstrapped the [Frontend Application](https://github.com/bounswe/bounswe2024group11/pull/183) |
| Created [Example Routes](https://github.com/bounswe/bounswe2024group11/pull/189) |
| Updated the [Project Plan](https://github.com/bounswe/bounswe2024group11/wiki/Project-Plan) to include detailed subtasks of frontend, backend, and mobile teams with [Muhammet Emin Çiftçi](https://github.com/meminciftci) and [Ozan Karakaya](https://github.com/ozankrkya) |
| Updated the [Class Diagram](https://github.com/bounswe/bounswe2024group11/wiki/Class-Diagrams) to add missing methods and moved every database methods into their respective controller class with [Mücahit Erdoğan Ünlü](https://github.com/MucahitErdoganUnlu) and [Ozan Karakaya](https://github.com/ozankrkya) |
| Updated the [Sequence Diagram](https://github.com/bounswe/bounswe2024group11/wiki/Sequence-Diagrams) to reflect changes of the class diagram and added search sequence diagram with [Mücahit Erdoğan Ünlü](https://github.com/MucahitErdoganUnlu) and [Ozan Karakaya](https://github.com/ozankrkya) |
| Created develop-web branch to separate production branch from the development branch which we push new features. The respective issue can be seen [here](https://github.com/bounswe/bounswe2024group11/issues/256) |
| Determined [subroutes and query parameters](https://github.com/bounswe/bounswe2024group11/issues/215) with [Ümit Can Evleksiz](https://github.com/umitcan07) |
| Created the [Login Page](https://github.com/bounswe/bounswe2024group11/pull/234) and [Ümit Can Evleksiz](https://github.com/umitcan07) helped to do styling |
| Designed [Initial Homepage](https://github.com/bounswe/bounswe2024group11/issues/318) and [Ümit Can Evleksiz](https://github.com/umitcan07) helped to do styling |
|[Implemented custom keyboard focus styling](https://github.com/bounswe/bounswe2024group11/issues/325) with [Ümit Can Evleksiz](https://github.com/umitcan07) |
| Replaced Dialog with Toast Notification component. [Issue](https://github.com/bounswe/bounswe2024group11/issues/339), [Pr](https://github.com/bounswe/bounswe2024group11/commit/a6e66b79ffd9fb7807761338285bac6d1d6bb97b) |
| Update project structure in readme. [Issue](https://github.com/bounswe/bounswe2024group11/issues/342) |
| Created the Initial Post Component. [Issue](https://github.com/bounswe/bounswe2024group11/issues/393), [Pr](https://github.com/bounswe/bounswe2024group11/pull/369) |
|Created Initial Profile Page UI. [Issue](https://github.com/bounswe/bounswe2024group11/issues/394), [Pr1](https://github.com/bounswe/bounswe2024group11/pull/369), [Pr2](https://github.com/bounswe/bounswe2024group11/pull/433) |
|Created Initial Post Feed UI. [Issue](https://github.com/bounswe/bounswe2024group11/issues/395), [Pr](https://github.com/bounswe/bounswe2024group11/pull/369) | Frontend |
| Created Modal UI For Create Post. [Issue](https://github.com/bounswe/bounswe2024group11/issues/396), [Pr](https://github.com/bounswe/bounswe2024group11/pull/369) |
| Implemented WikiData Search Endpoint with [Mücahit Erdoğan Ünlü](https://github.com/bounswe/bounswe2024group11/wiki/M%C3%BCcahit-Erdo%C4%9Fan-%C3%9Cnl%C3%BC) and [Ümit Can Evleksiz](https://github.com/bounswe/bounswe2024group11/wiki/%C3%9Cmit-Can-Evleksiz). [Issue](https://github.com/bounswe/bounswe2024group11/issues/424), [Pr](https://github.com/bounswe/bounswe2024group11/pull/426) |
#### Challanges Faced and Their Solutions
- I could not connect the web application to the back end. This was due many factors. We had a working back end at just night before the demo which was not enough to handle the errors like connecting wiki data search suggestions and wiki data search. However mobile team was able to connect to the back end because they had a more manual approach instead of the web team's approach which tried to utilize the power of libraries and best practices which led to us being more obsessed with complying to best practices instead of achieving the tasks. The web team could have implement the things in more manual fashion instead of relying functionalities provided by libraries which made harder and longer to solve errors.
- The styling using class variance authority was problematic for me. I could not overwrite the classes created by Ümit Can so I created my classes duplicating his classes and just changing few things. After consulting him I deleted unnecessary classes and used divs to encapsulate and style the element which has a styling to be overwritten.
- I could not run back end on my device. Mücahit helped me while creating the virtual environment and fixing errors while installing dependencies.
#### Sample API Call for `/v2/info`
##### How to Execute
- Curl
```
curl -X 'GET' \
'http://localhost:8000/api/v2/info/?qid=Q79037' \
-H 'accept: application/json' \
-H 'X-CSRFToken: Eh9GlB4uFzMjjk1Yn5Xc6gK7Zre16JX0O2q3bUMUCEc11FcwiD5kkuP7f7NQbOTf'
```
- Request Url
```
http://localhost:8000/api/v2/info/?qid=Q79037
```
Replace `Q79037` with the desired valid Qid to execute it.
##### Response Body
```json
{
"keyword": "Q79037",
"results": [
{
"Inception": "1962-08-01T00:00:00Z",
"Gender": "male",
"Birth Name": "Peter Benjamin Parker",
"Place of Birth": "Queens",
"Image": "Unknown",
"Description": "fictional character in Marvel Comics",
"Label": "Spider-Man"
}
]
}
```
#### Test Cases For Wiki Info Endpoint
```python
from django.urls import reverse
from rest_framework.test import APITestCase
class WikiInfoViewTestCase(APITestCase):
def test_wiki_info_view_with_valid_qid(self):
# Sending a GET request to the endpoint with a valid QID
response = self.client.get(reverse('info'), {'qid': 'Q2695156'})
# Asserting that the response status code is 200
self.assertEqual(response.status_code, 200)
# Asserting that the response contains the keyword 'results'
self.assertIn('results', response.data)
# Asserting that the response contains the keyword 'keyword' with the correct QID
self.assertEqual(response.data['keyword'], 'Q2695156')
# Asserting that the response contains data for the 'results' key
results = response.data['results']
self.assertIsInstance(results, list)
self.assertGreater(len(results), 0) # Asserting that results list is not empty
# Asserting the structure of each result item
for result in results:
self.assertIn('Inception', result)
self.assertIn('Gender', result)
self.assertIn('Birth Name', result)
self.assertIn('Place of Birth', result)
self.assertIn('Image', result)
self.assertIn('Description', result)
self.assertIn('Label', result)
def test_wiki_info_view_with_invalid_qid(self):
# Sending a GET request to the endpoint with an invalid QID
response = self.client.get(reverse('info'), {'qid': 'invalid_qid'})
# Asserting that the response status code is 404
self.assertEqual(response.status_code, 400)
# Asserting that the response contains the keyword 'res' with the error message
self.assertIn('res', response.data)
self.assertEqual(response.data['res'], 'QID should start with "Q".')
def test_wiki_info_view_without_qid(self):
# Sending a GET request to the endpoint without a QID
response = self.client.get(reverse('info'))
# Asserting that the response status code is 400
self.assertEqual(response.status_code, 400)
# Asserting that the response contains the keyword 'res' with the error message
self.assertIn('res', response.data)
self.assertEqual(response.data['res'], 'Parameter "qid" is required.')
```
<br />
### Ceydanur Şen
#### 3 Important Issues
- [Create an endpoint for the profile page](https://github.com/bounswe/bounswe2024group11/issues/388)
- [Implement 2 Wikidata and a Search API endpoints ](https://github.com/bounswe/bounswe2024group11/issues/347)
- [Create a Token Validation Mechanism for Registered User's Actions](https://github.com/bounswe/bounswe2024group11/issues/357)
#### Three Most Important PRs
- [feat(backend): add profile endpoint](https://github.com/bounswe/bounswe2024group11/pull/389)
- [feat: add new implementation for wikidata and search endpoints](https://github.com/bounswe/bounswe2024group11/pull/363)
- [feat(backend): add unique profiles for each user](https://github.com/bounswe/bounswe2024group11/pull/441)
#### Descriptions of Third-party APIs and the API functions Implemented
- Implemented an endpoint for the profile page with [Ozan Oytun Karakaya](https://github.com/bounswe/bounswe2024group11/wiki/Ozan-Oytun-Karakaya). While registering, user creates a profile page having features: biography, profile picture and username. Also each user can only have one unique profile page. User can update the fields totally or partialy afterwards.
##### The following is the sample api call for the profile endpoint (Partial Update):
```bash
curl -X PATCH http://164.90.189.150/api/v2/profiles/5/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_access_token" \
-d '{"profile_picture": "URL for the image"}' \
```
##### The following is the sample api call for the profile endpoint (GET):
```bash
curl -X GET http://164.90.189.150/api/v2/profiles/5/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzE2MTI5NjcwLCJpYXQiOjE3MTYwNDMyNzAsImp0aSI6IjRhNTNlZTNkZjU0YjRkOWZhM2VkYTcwNmJkZDljMmE2IiwidXNlcl9pZCI6NX0.myaRt08-TUQgYv0xHe70cOrWeokMfRixq0qM113wbTE"
```
##### The following is the sample api call for the profile endpoint (DELETE):
```bash
curl -X DELETE http://164.90.189.150/api/v2/profiles/5/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer access_token" \
```
- Implemented wikidata search queries used to implement WikidataSuggestionsView enpoint with [Mücahit Erdoğan Ünlü](https://github.com/bounswe/bounswe2024group11/wiki/M%C3%BCcahit-Erdo%C4%9Fan-%C3%9Cnl%C3%BC). After chosing filtering options such as born in and occupation, related wikidata entities are returned using this endpoint.
##### The followig is the sample api call for wikidata suggestions endpoint:
```bash
curl -X GET "http://164.90.189.150/api/v2/suggestions/?keyword= new york"
-H "Content-Type: application/json" \
```
##### Response Body:
```json
[
{
"qid": "Q60",
"label": "New York City",
"description": "most populous city in the United States"
},
{
"qid": "Q1384",
"label": "New York",
"description": "state of the United States of America"
},
...
]
```
#### Unit tests
- I did not implement a unit test for the parts I completed due to lack of time. However, I learned how to write unit tests from the documentation in our wiki throughly.
#### Description of Other Significant Work
- I searched and learned token validation mechanisms for the endpoints implemented.
- Decided on the query logic and the filtering options for the search functionality.
__Sample Semantic SPARQL Query:__
```SQL
SELECT DISTINCT ?item ?itemLabel (SUM(?sitelink) AS ?sitelinks)
WHERE {
?item wdt:P31 wd:Q1114461;
wdt:P106 wd:%s;
rdfs:label ?itemLabel.
?item wikibase:sitelinks ?sitelink.
FILTER(LANG(?itemLabel) ="en").
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
GROUP BY ?item ?itemLabel
ORDER BY DESC(?sitelinks)
```
I have implemented the semantic search queries for the various catagories we decided. Above, it can be seen a sample semantic sparql query implemented for "occupation" catagory.
#### Challanges Faced and Their Solutions
- Building API as a fundemental aspect of the backend development, I tried to learn RESTful principles, request/response handling, authentication, and serialization/deserialization concepts in a short amount of time. Since having no prior experience, learning and implementing these concepts were challenging. With the help of online tutorials and documentations, I implemented various functionalities for our backend side.
- I had hard time to solve the error handling part for the endpoint I implemented. At the beginning, I could not get the logic behind the error and spent a lot of time to solve the problem. I solved the issue with the help of my team.
<br />
### Mücahit Erdoğan Ünlü
#### Three Most Important Issues
- [Wikidata Suggestions and Post Search Endpoints Issue](https://github.com/bounswe/bounswe2024group11/issues/347)
- [Like Bookmark Counters on PostSerializer](https://github.com/bounswe/bounswe2024group11/issues/384)
- [Write Tutorials on Model, Serializer, and Views](https://github.com/bounswe/bounswe2024group11/issues/377). The importance is explained.
#### Three Most Important PRs
- [Wikidata Suggestions and Post Search Endpoints PR](https://github.com/bounswe/bounswe2024group11/pull/361) and [commit](https://github.com/bounswe/bounswe2024group11/commit/92964863d993c84d93f9b971c851f7566cdc3c49)
- [Like Bookmark Counters on PostSerializer](https://github.com/bounswe/bounswe2024group11/pull/385/files)
- [add is_follower field to postsearchserailizer and profileserializer](https://github.com/bounswe/bounswe2024group11/pull/442)
__Wiki documentation__
[Tutorial on Django Models](https://github.com/bounswe/bounswe2024group11/wiki/Tutorial-on-Django-Models)
[Tutorial on Django REST Serializers](https://github.com/bounswe/bounswe2024group11/wiki/Tutorial-on-Django-REST-Serializers)
[Tutorial on How to Implement A Django Rest API](https://github.com/bounswe/bounswe2024group11/wiki/Tutorial-on-How-to-Implement-A-Django-Rest-API-ViewSet)
[Tutorial on How to Write and Use Swagger API](https://github.com/bounswe/bounswe2024group11/wiki/Tutorial-on-How-to-Write-and-Use-Swagger-API)
[Tutorial to Write Unit Tests For Django REST API endpoints](https://github.com/bounswe/bounswe2024group11/wiki/Tutorial-to-Write-Tests-For-Django-REST-API-endpoints)
__Third Party Wikidata Search API__
In order to get the QID's of the user's search keys, I used
```python
url = f"https://www.wikidata.org/w/api.php?action=wbsearchentities&search={keyword}&language=en&format=json"
```
__Endpoint:__ https://www.wikidata.org/w/api.php
__Description:__ The Wikidata Search API allows users to search for Wikidata entities by a keyword.
Parameters:
__action:__ Specifies the action to be performed. For search, it is wbsearchentities.
__search:__ The keyword to search for.
__language:__ The language for the search results (e.g., en for English).
__format:__ The format of the response (e.g., json).
__Sample API Call__
```
https://www.wikidata.org/w/api.php?action=wbsearchentities&search=python&language=en&format=json
```
__Sample API Response__
```JSON
{
"searchinfo": {
"search": "python"
},
"search": [
{
"id": "Q28865",
"title": "Q28865",
"pageid": 32213,
"display": {
"label": {
"value": "Python",
"language": "en"
},
"description": {
"value": "general-purpose programming language",
"language": "en"
}
},
"repository": "wikidata",
"url": "//www.wikidata.org/wiki/Q28865",
"concepturi": "http://www.wikidata.org/entity/Q28865",
"label": "Python",
"description": "general-purpose programming language",
"match": {
"type": "label",
"language": "en",
"text": "Python"
}
},
{
"id": "Q271218",
"title": "Q271218",
"pageid": 262489,
"display": {
"label": {
"value": "Python",
"language": "en"
},
"description": {
"value": "genus of reptiles",
"language": "en"
}
},
"repository": "wikidata",
"url": "//www.wikidata.org/wiki/Q271218",
"concepturi": "http://www.wikidata.org/entity/Q271218",
"label": "Python",
"description": "genus of reptiles",
"match": {
"type": "label",
"language": "en",
"text": "Python"
}
},
```
#### __APIs That I implemented__
__Wikidata Suggestions API__
__Endpoint:__
```python
http://164.90.189.150:8000/api/v2/suggestions/
```
__keyword:__ The query parameter that is the keyword to search for.
__Method:__ GET
__Description:__ This API takes a keyword from the user and uses Third Party Wikidata API to get their QID's labels and descriptions so that a user can select what he means by a specific word. Then we can uses that QID to make a semantic search on Wikidata.
__Note:__ This could have used on frontend directly to make it more efficient; however, to have greater control over the query it is implemented on backend.
- The view checks for the presence of the "keyword" query parameter, makes an API call to Wikidata, and processes the response to return a simplified list of search results.
- Constructs the API URL using the provided keyword.
- Sends a GET request to the Wikidata API.
- If the response status code is 200, it processes the JSON response to extract the qid, label, and description fields from each search result and returns them in a simplified format.
- If the status code is not 200, it returns an error response with the appropriate status code.
- If an exception occurs, it returns a 500 INTERNAL SERVER ERROR response.
__Sample API Call__
`http://164.90.189.150:8000/api/v2/suggestions/?keyword=python`
__Sample Response__
```
[
{
"qid": "Q28865",
"label": "Python",
"description": "general-purpose programming language"
},
{
"qid": "Q271218",
"label": "Python",
"description": "genus of reptiles"
},
{
"qid": "Q15721",
"label": "Python",
"description": "earth-dragon of Delphi"
},
{
"qid": "Q599384",
"label": "CPython",
"description": "Python reference implementation"
},
{
"qid": "Q15728",
"label": "Python",
"description": "1978 air-to-air missile family by RAFAEL"
},
{
"qid": "Q4363952",
"label": "Python",
"description": "ancient peastan greek vase-painter of red-figure style"
},
{
"qid": "Q1249144",
"label": "Peithon",
"description": "Ancient Macedonian general"
}
]
```
__Sample API Call 2__
```
http://164.90.189.150:8000/api/v2/suggestions/
```
__Sample API Response__
```
{
"res": "Keyword parameter \"keyword\" is required."
}
```
__Post Search API__
__Endpoint:__
```
http://164.90.189.150:8000/api/v2/search/
```
__Description:__ It has 6 categories that a user must select one of them in the query parameter. According to the category, and the QID that is taken from the `suggestions` API call, a semantic Wikidata SPARQL query is run.
__Method:__ GET
- The code retrieves qid and category from the request query parameters.
- Returns a 400 BAD REQUEST response if either qid or category is missing.
- Based on the category, calls the corresponding helper function to fetch data that are related to the category from Wikidata.
- Extracts QIDs from the response data.
- When a GET method is called, it filters the Posts that have one of these QIDs in their tags.
- Serializes the filtered Post list queryset and returns the response.
- Returns a 500 INTERNAL SERVER ERROR response if any exception occurs.
__Sample Semantic SPARQL Query:__
```SQL
SELECT DISTINCT ?item ?itemLabel ?itemDescription ?sitelinks ?placeOfBirthLabel
WHERE {
?item wdt:P31 wd:Q1114461;
wdt:P19/wdt:P131* wd:%s;
wikibase:sitelinks ?sitelinks.
OPTIONAL{
?item wdt:P19 ?placeOfBirth.
?placeOfBirth rdfs:label ?placeOfBirthLabel.
FILTER(LANG(?placeOfBirthLabel) ="en").
}
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
}
ORDER BY DESC(?sitelinks)
```
__Sample API Call__
```
http://164.90.189.150:8000/api/v2/search/?category=occupation&qid=Q205375
```
Q205375 is the QID of the occupation `inventor` that is selected by user with the help of Wikidata API.
__Sample Response__
```
[
{
"id": 5,
"username": "memin41",
"user_id": "6",
"like_count": 3,
"bookmark_count": 1,
"liked_by": [
"memin41",
"ozankrk",
"Tatü"
],
"is_liked": false,
"is_bookmarked": false,
"is_following": false,
"title": "My Favorite Spider-Man Story Arc",
"content": "Just finished reading \"The Amazing Spider-Man: Birth of Venom\" and it was incredible! The origin of Venom is so well done, and the black suit saga is a must-read for any Spidey fan. Highly recommend it!",
"image_src": "https://www.artmajeur.com/medias/standard/k/o/konstantin1/artwork/17051995_f1a1bdec-1101-445e-b9b9-cb1f195c6981.jpg",
"qid": "Q79037",
"qtitle": "Spider-Man",
"created_at": "2024-05-17T06:51:49.392587Z",
"updated_at": "2024-05-17T06:51:49.392650Z"
},
{
"id": 15,
"username": "ozankrk",
"user_id": "5",
"like_count": 2,
"bookmark_count": 1,
"liked_by": [
"ozankrk",
"Tatü"
],
"is_liked": false,
"is_bookmarked": false,
"is_following": false,
"title": "The Genius Behind The Armor",
"content": "Let's chat about Iron Man! Tony Stark, the genius billionaire playboy philanthropist, is behind the iconic suit. His tech innovations and battles are legendary. What's your favorite Iron Man moment or suit?",
"image_src": "https://images.unsplash.com/photo-1635863138275-d9b33299680b?q=80&w=3731&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"qid": "Q180704",
"qtitle": "Iron Man",
"created_at": "2024-05-17T12:05:10.820919Z",
"updated_at": "2024-05-17T12:05:10.820974Z"
},
]
```
Both posts about Iron Man and Spider-Man are returned because they are both inventors according to Wikidata.
__Sample API Call 2__
```
http://164.90.189.150:8000/api/v2/search/?category=born%20in&qid=Q1408
```
Q1408 is the QID of the New Jersey State.
__Sample API Response 2__
```
[
{
"id": 7,
"username": "johnnyS",
"user_id": "8",
"like_count": 1,
"bookmark_count": 1,
"liked_by": [
"aa"
],
"is_liked": false,
"is_bookmarked": false,
"is_following": false,
"title": "Batman superior",
"content": "Just rewatched The Dark Knight and I'm blown away all over again! Batman is the ultimate symbol of resilience and justice. From his high-tech gadgets to his unwavering moral code, he proves you don't need superpowers to be a hero. Gotham's protector reminds us that anyone can make a difference. Who's your favorite Batman actor?",
"image_src": "https://images.unsplash.com/photo-1509347528160-9a9e33742cdb?q=80&w=3870&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"qid": "Q2695156",
"qtitle": "Batman",
"created_at": "2024-05-17T07:04:45.543620Z",
"updated_at": "2024-05-17T11:53:25.213652Z"
},
{
"id": 14,
"username": "emre",
"user_id": "3",
"like_count": 2,
"bookmark_count": 0,
"liked_by": [
"emre",
"aa"
],
"is_liked": false,
"is_bookmarked": false,
"is_following": false,
"title": "Tim Drake: The Third Robin",
"content": "Let's talk about Tim Drake, the third Robin! Tim is known for his detective skills, rivaling even Batman's. He figured out Batman's identity and convinced Bruce Wayne to let him become Robin after the tragic death of Jason Todd. What's your favorite Tim Drake moment?",
"image_src": "https://tse4.mm.bing.net/th?id=OIP.OnZvoxr8jPS5kPtFCLIchgHaHa&pid=Api",
"qid": "Q1076696",
"qtitle": "Tim Drake",
"created_at": "2024-05-17T11:58:46.708067Z",
"updated_at": "2024-05-17T11:58:46.708123Z"
}
]
```
__Sample API Call 3__
```
http://164.90.189.150:8000/api/v2/search/?category=enemy%20of&qid=Q1621261
```
Q1621261 is the QID of Venom the comics character.
```
[
{
"id": 17,
"username": "aa",
"user_id": "11",
"like_count": 1,
"bookmark_count": 0,
"liked_by": [
"Tatü"
],
"is_liked": false,
"is_bookmarked": false,
"is_following": false,
"title": "title",
"content": "123",
"image_src": "",
"qid": "Q79037",
"qtitle": "Spider-Man",
"created_at": "2024-05-17T13:38:51.516627Z",
"updated_at": "2024-05-17T13:38:51.516682Z"
},
{
"id": 20,
"username": "tenacke",
"user_id": "10",
"like_count": 1,
"bookmark_count": 1,
"liked_by": [
"tenacke"
],
"is_liked": false,
"is_bookmarked": false,
"is_following": false,
"title": "Why Carnage Hates Venom",
"content": "Carnage despises Venom because of their twisted family dynamic. Born from Venom's symbiote, Carnage sees Venom as a father figure he must rebel against. Their differing ideologies and Carnage's inherent chaos further fuel their hatred. It's a brutal clash of family and ferocity!",
"image_src": "https://i.hizliresim.com/cxko7pn.jpg",
"qid": "Q1753328",
"qtitle": "Carnage",
"created_at": "2024-05-19T01:37:01.258307Z",
"updated_at": "2024-05-19T01:42:20.185308Z"
}
]
```
Both Posts about Carnage and Spider-Man are returned since they are both enemies of Venom.
__Unit Tests for Search Post__
```
def test_missing_parameters(self):
url = reverse("search_posts")
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_born_in_category(self, mock_born_in_wikidata):
url = reverse("search_posts")
response = self.client.get(url, {"qid": "Q123", "category": "born in"})
self.assertEqual(response.status_code, status.HTTP_200_OK)
```
__Unit Tests for Wikidata Suggestions__
```
def test_missing_keyword_parameter(self):
url = reverse("wikidata_suggestions")
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_valid_qid(self):
url = reverse("wikidata_suggestions")
response = self.client.get(url, {"keyword": "apple"})
self.assertEqual(response.status_code, status.HTTP_200_OK)
```
__Challenges Faced During Implementation And Their Solutions__
- I realized that me and my teammates started implementation without basic knowledge about Django and Django REST. Since we lacked theoretical knowledge, the project that we prepared before Milestone 2 was alien and hard to refactor for us. This resulted in building the backend app from scratch once more. This meant that we did not even have the register and login functionalities that we already built. Therefore, I have prepared three-paged tutorial where I introduced Models, Serializers, and Views. Their relationship is the core of the Django REST. However, it was already too late. This is why, as I mentioned in `Most Important Three Issues`, learning and preparing a tutorial about Django REST was important.
- Since as a backend team we were already very late, the first join of the backend part and the frontend part of the code happened very late. Therefore, we could not have time to fix the code and have a properly working project.
- The most important difficulty was the management of time. Since we had other projects as challenging and time consuming as this one (especially 321 projects), we could not manage to focus on this project.
- For me, one of the most challenging part of the project was the stress management. We entered the last week and our team started to build the backend app from the start. They also started to use viewsets which I think were unnecessary and made the implementation hard because in order to effectively use a library, you had to know it well. Instead of this, building a view from scratch would be very helpful and easy for us to maintain the code. However, the disaggrement continued and we failed to create a properly working backend.
<br />
### Arda Vural
#### 3 Important Issues
- [Create Project Plan](https://github.com/bounswe/bounswe2024group11/issues/72): This issue covers our overall project plan that we have done in the arly stages of the project. I have completed it with Ozan Karakaya and Muhamet Emin Çiftçi.
- [Implement Login Page for Mobile](https://github.com/bounswe/bounswe2024group11/issues/235): This issue covers the implementation of login-page, local storage method with "remember me" feature and navigation between screens. Also, authentication process is implemented in another issue which is connected with that issue.
- [Implement the Post Component for Feed and Search Pages for the Mobile](https://github.com/bounswe/bounswe2024group11/issues/351): This issue covers the implementation of post component which is implemented dynamically to be used in different pages.
#### 3 Important Pull Requests
- feat(mobile): add login screen [#242](https://github.com/bounswe/bounswe2024group11/pull/242):
- This PR covers the implementation of login screen to be used in authentication.
- feat(mobile): added async and storage methods [#300](https://github.com/bounswe/bounswe2024group11/pull/300):
- This PR adds more functionality to the login screen such as "remember me" feature to keep user logged in using local storage functions.
- feat(mobile): Post Screen and Navigation added [#373](https://github.com/bounswe/bounswe2024group11/pull/373)
- This PR covers the implementation of Post Screen and Post Components which is clickable and they navigate through app.
#### Wiki Documentations
- You can find the [Project Plan Documentation](https://github.com/bounswe/bounswe2024group11/wiki/Project-Plan) in Wiki. We have planned our project detailly and created a documentation for our team to provide a good and readable plan with Ozan Karakaya and Muhammet Emin Çiftçi.
#### Description of API
- I have helped and contributed to the implementation of get `/api/v2/posts/` endpoint. Firstly, we need to login to get our token from the `/api/v2/login/` endpoint by providing the credentials for our user. For the sample calls below, I will be using the token of `@memin41` test user. Then, we are going to use our token and post endpoint with `post_id`.
- To use return of the information about any post, the `post_id` should be added at the end of the URL. Here, we wil return the post with related `post_id: 15`.
```bash
curl -X GET http://164.90.189.150/api/v2/posts/15/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzE2MTU3NDI4LCJpYXQiOjE3MTYwNzEwMjgsImp0aSI6IjdjYzNhNTdhOGM3ZDQ0OTE5N2I5MmE3ZjQzMWFkOGM1IiwidXNlcl9pZCI6Nn0.sCYavXIHGEv4LvdIzLxzPTgUHOxpLiPie3zpmWNCjvY"
```
- After using that, we can get information about the author of the post, post's like attributes , bookmark attributes, content, title and more.
```json
{"id":15,"author_profile":
{"id":5,
"username":"ozankrk",
"email":"ozan@gmail.com",
"fullname":"Ozan Oytun",
"picture":"https://i.ibb.co/kHBtv0g/zenith.png",
"biography":"Interested in Marvel"},
"like_count":2,
"bookmark_count":1,
"liked_by":["ozankrk","Tatü"],
"is_liked":false,
"is_bookmarked":false,
"is_following":true,
"title":"The Genius Behind The Armor",
"content":"Let's chat about Iron Man! Tony Stark, the genius billionaire playboy philanthropist, is behind the iconic suit. His tech innovations and battles are legendary. What's your favorite Iron Man moment or suit?",
"image_src":"https://images.unsplash.com/photo-1635863138275-d9b33299680b?q=80&w=3731&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"qid":"Q180704",
"qtitle":"Iron Man",
"created_at":"2024-05-17T12:05:10.820919Z",
"updated_at":"2024-05-17T12:05:10.820974Z",
"author":5}
```
- If the token of the user to get this post is not given as header;
```bash
$ curl -X GET http://164.90.189.150/api/v2/posts/15/
-H "Content-Type: application/json"
```
- response code: 403
```json
{"detail":"Authentication credentials were not provided."}
```
#### Description of Unit Tests
- I did not implement the unit test for this endpoint but I learnt how to code unit tests and how they work through our own documentation in wiki.
#### Challenges Faced During Implementation And Their Solutions
- The first challenge as a mobile team member was to learn and deep dive into mobile app dynamics. Since none of us as a mobile team have experiences, it was really hard to plan. We could not estimate the learning time cost exaclty because we were all unexperienced. Still, we succeed to be a good team and helped each other in every way to make everything easier for everyone. Everbody started to learn something about mobile development and did their job perfectly in the end.
- The second challenge for me was using typescript. We chose to use typescript in the beginning to write a safer code but it caused more problems than we expected since we were lack of information both typescript and mobile. So, we needed to spend extra time on typescript . But we handled that problem by taking help from the ones who know typescript properly and also using other sources.
- Another challenge was communication with backend team because one of the teams always had some problems and things didnt go as planned. That caused the teams to make some assumptions which caused issues such as wrong decisions on design. To solve this problem, one of our members was communicating with other team every day even if we do not encounter any specific problem.
<br />