Skip to content

Commit d0bd685

Browse files
authored
Merge pull request #14 from TheTrustyPwo/lastminutechanges
Lastminutechanges
2 parents 1ea51d5 + cd63f7a commit d0bd685

File tree

8 files changed

+54
-115
lines changed

8 files changed

+54
-115
lines changed

app/auth/auth_service.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import requests
21
from flask_login import login_user, logout_user
32
from passlib.hash import bcrypt
43

@@ -34,8 +33,6 @@ def log_in_user(email, password):
3433
:rtype: bool
3534
"""
3635
user = User.get_by_email(email.lower())
37-
if not user or user.password is None:
38-
return False
3936
if user and bcrypt.verify(password, user.password):
4037
login_user(user)
4138
return True
@@ -47,7 +44,3 @@ def log_out_user():
4744
Logs the current user out.
4845
"""
4946
logout_user()
50-
51-
52-
def get_google_provider_cfg():
53-
return requests.get('https://accounts.google.com/.well-known/openid-configuration').json()

app/auth/routes.py

Lines changed: 2 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
1-
from flask import flash, redirect, render_template, request, url_for, current_app
2-
from flask_login import current_user, login_required, login_user
3-
import json
4-
import requests
1+
from flask import flash, redirect, render_template, request, url_for
2+
from flask_login import current_user, login_required
53

6-
from app import oauth_client
74
from app.auth import auth_blueprint, auth_service
85
from app.auth.forms import RegisterForm, LoginForm
9-
from app.models import User
106

117

128
@auth_blueprint.route("/register", methods=["GET", "POST"])
@@ -70,64 +66,6 @@ def login():
7066
return render_template("login.html", form=form)
7167

7268

73-
@auth_blueprint.route("/login/google")
74-
def login_google():
75-
google_provider_cfg = auth_service.get_google_provider_cfg()
76-
authorization_endpoint = google_provider_cfg["authorization_endpoint"]
77-
78-
request_uri = oauth_client.prepare_request_uri(
79-
authorization_endpoint,
80-
redirect_uri=request.base_url + "/callback",
81-
scope=["openid", "email", "profile"],
82-
)
83-
return redirect(request_uri)
84-
85-
86-
@auth_blueprint.route("/login/google/callback")
87-
def login_google_callback():
88-
code = request.args.get("code")
89-
90-
google_provider_cfg = auth_service.get_google_provider_cfg()
91-
token_endpoint = google_provider_cfg["token_endpoint"]
92-
93-
token_url, headers, body = oauth_client.prepare_token_request(
94-
token_endpoint,
95-
authorization_response=request.url,
96-
redirect_url=request.base_url,
97-
code=code
98-
)
99-
100-
token_response = requests.post(
101-
token_url,
102-
headers=headers,
103-
data=body,
104-
auth=(current_app.config['GOOGLE_CLIENT_ID'], current_app.config['GOOGLE_CLIENT_SECRET']),
105-
)
106-
107-
oauth_client.parse_request_body_response(json.dumps(token_response.json()))
108-
109-
userinfo_endpoint = google_provider_cfg["userinfo_endpoint"]
110-
uri, headers, body = oauth_client.add_token(userinfo_endpoint)
111-
userinfo_response = requests.get(uri, headers=headers, data=body)
112-
113-
if not userinfo_response.json().get("email_verified"):
114-
flash("Login Failed: Email not verified", "danger")
115-
return redirect(url_for("auth.login"))
116-
117-
email = userinfo_response.json()["email"]
118-
picture = userinfo_response.json()["picture"]
119-
username = userinfo_response.json()["given_name"]
120-
121-
user = User.get_by_email(email)
122-
if not user:
123-
user = User(email=email, username=username, password=None)
124-
user.save()
125-
126-
login_user(user)
127-
128-
return redirect(url_for('feed.home'))
129-
130-
13169
@auth_blueprint.route("/logout", methods=["POST"])
13270
@login_required
13371
def logout():

app/static/css/style.css

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4787,7 +4787,7 @@ select.sort {
47874787
.modal-popup-body,
47884788
.chat-wrapper,
47894789
.chat-left {
4790-
height: calc(90vh - 100px);
4790+
height: calc(100vh - 120px);
47914791
}
47924792
.modal-popup-body::-webkit-scrollbar-track,
47934793
.chat-wrapper::-webkit-scrollbar-track,
@@ -5105,17 +5105,17 @@ select.sort {
51055105
margin: 0 5px;
51065106
position: relative;
51075107
}
5108-
/*.chat-form .form-group:after {*/
5109-
/* background-color: var(--theme-color);*/
5110-
/* opacity: 0.08;*/
5111-
/* width: 100%;*/
5112-
/* height: 100%;*/
5113-
/* content: "";*/
5114-
/* position: absolute;*/
5115-
/* top: 0;*/
5116-
/* left: 0;*/
5117-
/* border-radius: 30px;*/
5118-
/*}*/
5108+
.chat-form .form-group:after {
5109+
background-color: var(--theme-color);
5110+
opacity: 0.08;
5111+
width: 100%;
5112+
height: 100%;
5113+
content: "";
5114+
position: absolute;
5115+
top: 0;
5116+
left: 0;
5117+
border-radius: 30px;
5118+
}
51195119
.chat-form input {
51205120
width: 100%;
51215121
border: 0;
@@ -5171,6 +5171,7 @@ select.sort {
51715171
-moz-box-align: start;
51725172
-ms-flex-align: start;
51735173
align-items: flex-start;
5174+
padding-bottom: 70px !important;
51745175
}
51755176
.chat-body .messages-content .message-item.outgoing-message {
51765177
margin-left: auto;
@@ -6081,4 +6082,4 @@ select.sort {
60816082
border-color: #eee !important;
60826083
pointer-events: none !important;
60836084
animation: loading-skeleton 1s infinite alternate !important;
6084-
}
6085+
}

app/static/js/home.js

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ function createPostCard(post) {
6565
<h4 class="fw-bold font-xs">${post.title}</h4>
6666
<div class="card-body p-0 me-lg-5">
6767
<p class="fw-500 text-grey-500 lh-26 font-xssss w-100 mb-2">
68-
${post.body.length > 300 ? `${post.body.slice(0, 300)} <a href="/post/${post.id}" class="fw-600 text-primary ms-2">See more</a>` : post.body}
68+
${post.body.length > 150 ? `${post.body.slice(0, 150)} <a href="/post/${post.id}" class="fw-600 text-primary ms-2">See more</a>` : post.body}
6969
</p>
7070
</div>
7171
@@ -89,12 +89,12 @@ function createPostCard(post) {
8989
<span class="d-none-xss">${post.replyCount} Replies</span>
9090
</a>
9191
92-
<div id="share" class="pointer ms-auto d-flex align-items-center fw-600 text-grey-900 text-dark lh-26 font-xssss" id="shareDropdown" data-bs-toggle="dropdown" aria-expanded="false">
92+
<div class="pointer ms-auto d-flex align-items-center fw-600 text-grey-900 text-dark lh-26 font-xssss" id="dropdownMenu32" data-bs-toggle="dropdown" aria-expanded="false">
9393
<i class="feather-share-2 text-grey-900 text-dark btn-round-sm font-lg"></i>
9494
<span class="d-none-xs">Share</span>
9595
</div>
9696
97-
<div class="dropdown-menu dropdown-menu-end p-4 rounded-xxl border-0 shadow-lg right-0 " aria-labelledby="shareDropdown">
97+
<div class="dropdown-menu dropdown-menu-end p-4 rounded-xxl border-0 shadow-lg right-0 " aria-labelledby="dropdownMenu32">
9898
<h4 class="fw-700 font-xss text-grey-900 d-flex align-items-center">Share <i class="feather-x ms-auto font-xssss btn-round-xs bg-greylight text-grey-900 me-2"></i></h4>
9999
<div class="card-body p-0 d-flex">
100100
<ul class="d-flex align-items-center justify-content-between mt-2">
@@ -106,23 +106,12 @@ function createPostCard(post) {
106106
</ul>
107107
</div>
108108
<h4 class="fw-700 font-xssss mt-4 text-grey-500 d-flex align-items-center mb-3">Copy Link</h4>
109-
<i id="copy-link" class="feather-copy position-absolute right-35 mt-3 font-xs text-grey-500"></i>
110-
<input id="post-link" type="text" value="https://studyhub.thepwo.com/post/${post.id}" class="bg-grey text-grey-700 border-0 lh-32 p-2 font-xssss fw-600 rounded-3 w-100 theme-dark-bg" disabled>
109+
<i class="feather-copy position-absolute right-35 mt-3 font-xs text-grey-500"></i>
110+
<input type="text" placeholder="https://studyhub.thepwo.com/post/${post.id}" class="bg-grey text-grey-500 font-xssss border-0 lh-32 p-2 font-xssss fw-600 rounded-3 w-100 theme-dark-bg">
111111
</div>
112-
</div>`);
113-
114-
postCard.onclick = () => {
115-
location.href = `/post/${post.id}`;
116-
}
117-
118-
postCard.querySelector('#share').onclick = (event) => event.stopPropagation();
119-
postCard.querySelector('#copy-link').onclick = () => {
120-
const postLink = postCard.querySelector('#post-link');
121-
postLink.select();
122-
postLink.setSelectionRange(0, 99999);
123-
navigator.clipboard.writeText(postLink.value);
124-
}
112+
</div>`)
125113

114+
postCard.onclick = () => window.location.href = `/post/${post.id}`;
126115
return postCard;
127116
}
128117

app/static/js/models/conversation.js

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,22 @@ import Message from "./message.js";
33

44
// Establish a socket connection
55
const socket = io.connect(`/messages/socket`, {rememberTransport: false});
6-
const current = await User.getCurrent()
6+
7+
// Listen for new message events
8+
socket.on('new_message', async message => {
9+
// Extract message properties
10+
const {id, senderId, conversationId, content, timestamp, readUserIds} = message;
11+
12+
// Get sender and conversation objects
13+
const sender = await User.getById(senderId);
14+
const conversation = await Conversation.getById(conversationId);
15+
16+
// Get read users
17+
const readUsers = await Promise.all(readUserIds.map(async userId => await User.getById(userId)));
18+
19+
// Create a new Message object and add it to the conversation history
20+
conversation.history.push(new Message(id, sender, conversation, content, new Date(timestamp), new Set(readUsers)));
21+
});
722

823
class Conversation {
924
// Static cache map for storing Conversation objects
@@ -55,10 +70,15 @@ class Conversation {
5570
}
5671
}
5772

73+
/**
74+
* Get all conversations
75+
* @returns {Array<Conversation>} - An array of Conversation objects
76+
*/
5877
static async getAll() {
5978
const response = await fetch(`/api/v1/conversations/all`);
6079
const data = await response.json();
61-
return Promise.all(data.map(async conversationData => await Conversation.fromJson(conversationData)));
80+
const conversations = await Promise.all(data.map(async conversationData => await Conversation.fromJson(conversationData)));
81+
return conversations.filter(convo => convo !== undefined);
6282
}
6383

6484
/**
@@ -109,7 +129,6 @@ class Conversation {
109129
const readUsers = await Promise.all(readUserIds.map(async userId => await User.getById(userId)));
110130
return new Message(id, sender, this, content, moment.utc(timestamp), new Set(readUsers));
111131
}));
112-
this.history.sort((a, b) => b.timestamp - a.timestamp);
113132
}
114133

115134
/**
@@ -133,15 +152,10 @@ class Conversation {
133152
* Get the last message in the conversation
134153
* @returns {Message|undefined} - The last Message object in the conversation or undefined if no messages
135154
*/
136-
get latestMessage() {
155+
getLastMessage() {
137156
if (this.history.length === 0) return undefined;
138157
return this.history[this.history.length - 1];
139158
}
140-
141-
get image() {
142-
if (this.isGroup) return `/static/assets/default-group.png`;
143-
else return Array.from(this.users).find(user => user.id !== current.id).pfp;
144-
}
145159
}
146160

147161
export default Conversation;

app/static/js/models/user.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,17 @@ class User {
1111
* @param {string} username - The username of the user
1212
* @param {Date} dateCreated - The date the user was created
1313
* @param {string} pfp - The profile picture URL of the user
14+
* @param answered
1415
*/
15-
constructor(id, email, username, dateCreated, pfp) {
16+
constructor(id, email, username, dateCreated, pfp, answered) {
1617
if (User.#cache.has(id)) return User.#cache.get(id);
1718

1819
this.id = id;
1920
this.email = email;
2021
this.username = username;
2122
this.dateCreated = dateCreated;
2223
this.pfp = pfp;
24+
this.answered = answered;
2325
User.#cache.set(id, this);
2426
}
2527

@@ -42,8 +44,8 @@ class User {
4244
* @returns {User} - The created User object
4345
*/
4446
static fromJson(json) {
45-
const { id, email, username, dateCreated, pfp } = json;
46-
return new User(id, email, username, moment.utc(dateCreated), pfp);
47+
const { id, email, username, dateCreated, pfp, answered } = json;
48+
return new User(id, email, username, moment.utc(dateCreated), pfp, answered);
4749
}
4850

4951
/**

app/static/js/users.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ $(document).ready(async function () {
2626
document.getElementById("message").style.visibility = "visible";
2727
document.getElementById("profile-picture").remove();
2828
}
29-
29+
document.getElementById("reputation").innerText = "Reputation: " + user.answered.toLocaleString();
3030
await fetchUserPosts();
3131
});
3232

app/templates/user.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ <h4 class="fw-700 font-sm mt-2 mb-lg-5 mb-4 pl-15">
4848
<span id="username">Loading...</span>
4949
<span class="fw-500 font-xssss text-grey-500 mt-1 mb-3 d-block" id="email">Loading...</span>
5050
</h4>
51+
<span class="z-index-1 position-absolute-md text-black font-xss text-uppercase fw-700 ls-3"
52+
style="right: 400px !important; transform: translateY(-300%)" id="reputation">Loading...</span>
5153
<div class="d-flex align-items-center justify-content-center position-absolute-md right-15 top-0 me-2">
5254
<a class="d-none d-lg-block bg-success p-3 z-index-1 rounded-3 text-white font-xsssss text-uppercase fw-700 ls-3"
5355
id="message" style="visibility: hidden">Message</a>

0 commit comments

Comments
 (0)