added feeds

master
Mathias Rothenhaeusler 2023-09-17 11:54:37 +02:00
parent 018bbf3918
commit 43e5d473b7
21 changed files with 76 additions and 25 deletions

View File

@ -9,3 +9,8 @@ services:
- "POSTGRES_USER=admin" - "POSTGRES_USER=admin"
- "POSTGRES_DB=rss" - "POSTGRES_DB=rss"
- "POSTGRES_PASSWORD=secret+123" - "POSTGRES_PASSWORD=secret+123"
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:

View File

@ -1,4 +1,3 @@
use super::jwt; use super::jwt;
use actix_web::dev::ServiceRequest; use actix_web::dev::ServiceRequest;
@ -10,9 +9,13 @@ pub fn check_password(password: String) -> Result<String, &'static str> {
} }
pub fn extract_header_token(request: &ServiceRequest) -> Result<String, &'static str> { pub fn extract_header_token(request: &ServiceRequest) -> Result<String, &'static str> {
log::info!("Request: {:?}", request);
match request.headers().get("user-token") { match request.headers().get("user-token") {
Some(token) => match token.to_str() { Some(token) => match token.to_str() {
Ok(processed_password) => Ok(String::from(processed_password)), Ok(processed_password) => {
log::info!("Token provided: {}", processed_password);
Ok(String::from(processed_password))
}
Err(_processed_password) => Err("there was an error processing token"), Err(_processed_password) => Err("there was an error processing token"),
}, },
None => Err("there is no token"), None => Err("there is no token"),

View File

@ -4,4 +4,5 @@ use serde::Deserialize;
pub struct NewFeedSchema { pub struct NewFeedSchema {
pub title: String, pub title: String,
pub url: String, pub url: String,
pub user_id: i32,
} }

View File

@ -23,7 +23,7 @@ async fn main() -> std::io::Result<()> {
let request_url: String = String::from(req.uri().path().clone()); let request_url: String = String::from(req.uri().path().clone());
log::info!("Request Url: {}", request_url); log::info!("Request Url: {}", request_url);
if req.path().contains("/reader/") { if req.path().contains("/article/") {
match auth::process_token(&req) { match auth::process_token(&req) {
Ok(_token) => passed = true, Ok(_token) => passed = true,
Err(_message) => passed = false, Err(_message) => passed = false,

View File

@ -1,2 +1,2 @@
pub mod feed;
pub mod new_feed; pub mod new_feed;
pub mod rss_feed;

View File

@ -6,10 +6,15 @@ use diesel::Insertable;
pub struct NewFeed { pub struct NewFeed {
pub title: String, pub title: String,
pub url: String, pub url: String,
pub user_id: i32,
} }
impl NewFeed { impl NewFeed {
pub fn new(title: String, url: String) -> NewFeed { pub fn new(title: String, url: String, user_id: i32) -> NewFeed {
NewFeed { title, url } NewFeed {
title,
url,
user_id,
}
} }
} }

View File

@ -1,4 +1,4 @@
use super::super::user::user::User; use super::super::user::rss_user::User;
use crate::schema::feed; use crate::schema::feed;
use diesel::{Associations, Identifiable, Queryable}; use diesel::{Associations, Identifiable, Queryable};

View File

@ -1 +1 @@
mod feed_item; mod rss_feed_item;

View File

@ -1,3 +1,2 @@
pub mod new_user; pub mod new_user;
pub mod user; pub mod rss_user;

View File

@ -10,8 +10,9 @@ pub async fn add(new_feed: web::Json<NewFeedSchema>) -> HttpResponse {
let mut connection = establish_connection(); let mut connection = establish_connection();
let title: String = new_feed.title.clone(); let title: String = new_feed.title.clone();
let url: String = new_feed.url.clone(); let url: String = new_feed.url.clone();
let user_id: i32 = new_feed.user_id;
let new_feed = NewFeed::new(title, url); let new_feed = NewFeed::new(title, url, user_id);
let insert_result = diesel::insert_into(feed::table) let insert_result = diesel::insert_into(feed::table)
.values(&new_feed) .values(&new_feed)
@ -19,6 +20,9 @@ pub async fn add(new_feed: web::Json<NewFeedSchema>) -> HttpResponse {
match insert_result { match insert_result {
Ok(_) => HttpResponse::Created().await.unwrap(), Ok(_) => HttpResponse::Created().await.unwrap(),
Err(_) => HttpResponse::Conflict().await.unwrap(), Err(e) => {
log::error!("{e}");
HttpResponse::Conflict().await.unwrap()
}
} }
} }

View File

@ -5,6 +5,7 @@ mod add;
pub mod feeds; pub mod feeds;
mod get; mod get;
pub mod structs; pub mod structs;
mod sync;
pub fn feed_factory(app: &mut web::ServiceConfig) { pub fn feed_factory(app: &mut web::ServiceConfig) {
let base_path: Path = Path { let base_path: Path = Path {
@ -19,4 +20,8 @@ pub fn feed_factory(app: &mut web::ServiceConfig) {
&base_path.define(String::from("/add")), &base_path.define(String::from("/add")),
web::post().to(add::add), web::post().to(add::add),
); );
app.route(
&base_path.define(String::from("/sync")),
web::post().to(sync::sync),
);
} }

View File

@ -7,3 +7,9 @@ pub struct Feed {
pub title: String, pub title: String,
pub items: Vec<Article>, pub items: Vec<Article>,
} }
impl Feed {
pub fn new(title: String, items: Vec<Article>) -> Feed {
Feed { title, items }
}
}

12
src/reader/sync.rs 100644
View File

@ -0,0 +1,12 @@
use actix_web::{HttpRequest, Responder};
use diesel::prelude::*;
use crate::{database::establish_connection, schema::feed};
use super::structs::feed::Feed;
pub async fn sync(req: HttpRequest) -> impl Responder {
let mut connection: diesel::PgConnection = establish_connection();
let users = feed::table.load::<Feed>(&mut connection).unwrap();
}

View File

@ -1,7 +1,7 @@
use crate::database::establish_connection; use crate::database::establish_connection;
use crate::diesel; use crate::diesel;
use crate::json_serialization::login::Login; use crate::json_serialization::login::Login;
use crate::models::user::user::User; use crate::models::user::rss_user::User;
use crate::schema::users; use crate::schema::users;
use crate::{auth::jwt::JwtToken, schema::users::username}; use crate::{auth::jwt::JwtToken, schema::users::username};
use actix_web::{web, HttpResponse}; use actix_web::{web, HttpResponse};
@ -13,7 +13,7 @@ pub async fn login(credentials: web::Json<Login>) -> HttpResponse {
let mut connection = establish_connection(); let mut connection = establish_connection();
let users = users::table let users: Vec<User> = users::table
.filter(username.eq(username_cred.as_str())) .filter(username.eq(username_cred.as_str()))
.load::<User>(&mut connection) .load::<User>(&mut connection)
.unwrap(); .unwrap();
@ -32,10 +32,11 @@ pub async fn login(credentials: web::Json<Login>) -> HttpResponse {
match user.clone().verify(password) { match user.clone().verify(password) {
true => { true => {
log::info!("verified password successfully"); log::info!("verified password successfully for user {}", user.id);
let token: String = JwtToken::encode(user.clone().id); let token: String = JwtToken::encode(user.clone().id);
HttpResponse::Ok() HttpResponse::Ok()
.insert_header(("token", token)) .insert_header(("token", token))
.insert_header(("user_id", user.id))
.await .await
.unwrap() .unwrap()
} }

8
vue/package-lock.json generated
View File

@ -10,7 +10,8 @@
"dependencies": { "dependencies": {
"axios": "^1.5.0", "axios": "^1.5.0",
"vue": "^3.3.4", "vue": "^3.3.4",
"vue-router": "^4.2.4" "vue-router": "^4.2.4",
"vue-sessionstorage": "^1.0.0"
}, },
"devDependencies": { "devDependencies": {
"@rushstack/eslint-patch": "^1.3.2", "@rushstack/eslint-patch": "^1.3.2",
@ -2694,6 +2695,11 @@
"vue": "^3.2.0" "vue": "^3.2.0"
} }
}, },
"node_modules/vue-sessionstorage": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/vue-sessionstorage/-/vue-sessionstorage-1.0.0.tgz",
"integrity": "sha512-Axo8oY/3gcmU+OdsB/zePuoBCqmyjB2/ORUTrC/WVFm8OkMp8yYlzz6nOOzIU1Tgg6a4ogBaUa3loPtHROotbQ=="
},
"node_modules/which": { "node_modules/which": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@ -12,7 +12,8 @@
"dependencies": { "dependencies": {
"axios": "^1.5.0", "axios": "^1.5.0",
"vue": "^3.3.4", "vue": "^3.3.4",
"vue-router": "^4.2.4" "vue-router": "^4.2.4",
"vue-sessionstorage": "^1.0.0"
}, },
"devDependencies": { "devDependencies": {
"@rushstack/eslint-patch": "^1.3.2", "@rushstack/eslint-patch": "^1.3.2",

View File

@ -15,7 +15,7 @@ async function login() {
const jsonData = JSON.stringify(loginData) const jsonData = JSON.stringify(loginData)
console.log('test') console.log('test')
try { try {
const response = await axios.post('login', jsonData, { const response = await axios.post('login/rss', jsonData, {
headers: { headers: {
'Content-Type': 'application/json', // Set the content type to JSON 'Content-Type': 'application/json', // Set the content type to JSON
'crossDomain': true, 'crossDomain': true,
@ -33,7 +33,11 @@ async function login() {
if (response.status == 200) { if (response.status == 200) {
let token = response.headers.token let token = response.headers.token
localStorage.setItem("user-token", token); let user_id = response.headers.user_id
localStorage.setItem("user-token", token)
localStorage.setItem("user-id", user_id)
sessionStorage.setItem("user-id", user_id)
sessionStorage.setItem("user-token", token)
router.push({ name: 'about' }) router.push({ name: 'about' })
} }
// Handle success // Handle success

View File

@ -3,7 +3,6 @@ import './assets/main.css'
import { createApp } from 'vue' import { createApp } from 'vue'
import App from './App.vue' import App from './App.vue'
import router from './router' import router from './router'
const app = createApp(App) const app = createApp(App)
app.use(router) app.use(router)

View File

@ -16,17 +16,17 @@ export default defineConfig({
server: { server: {
proxy: { proxy: {
'/login': { '/login/rss': {
target: 'http://localhost:8001/api/v1/auth', target: 'http://localhost:8001/api/v1/auth/login',
changeOrigin: true, changeOrigin: true,
secure: false, secure: false,
// rewrite: (path) => path.replace(/^\/api/, ''), rewrite: (path) => path.replace(/^\/login\/rss/, ''),
}, },
'/feeds': { '/feeds/get': {
target: 'http://localhost:8001/api/v1/article/get', target: 'http://localhost:8001/api/v1/article/get',
changeOrigin: true, changeOrigin: true,
secure: false, secure: false,
rewrite: (path) => path.replace(/^\/feeds/, ''), rewrite: (path) => path.replace(/^\/feeds\/get/, ''),
}, },
}, },
cors: false cors: false