create & getall for tags
This commit is contained in:
@@ -33,6 +33,8 @@ pub fn api_router() -> Router {
|
|||||||
.route("/api/sessions/{id}", get(sessions::get_by_id))
|
.route("/api/sessions/{id}", get(sessions::get_by_id))
|
||||||
.route("/api/sessions/{id}/revoke", post(sessions::revoke_by_id))
|
.route("/api/sessions/{id}/revoke", post(sessions::revoke_by_id))
|
||||||
//
|
//
|
||||||
|
.route("/api/tags", get(tags::get_all))
|
||||||
|
.route("/api/tags", post(tags::create))
|
||||||
.route("/api/tags/{id}", get(tags::get_by_id))
|
.route("/api/tags/{id}", get(tags::get_by_id))
|
||||||
.route("/api/tags/#{name}", get(tags::get_by_name))
|
.route("/api/tags/#{name}", get(tags::get_by_name))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use axum::{
|
|||||||
http::HeaderMap,
|
http::HeaderMap,
|
||||||
response::{IntoResponse, Response},
|
response::{IntoResponse, Response},
|
||||||
};
|
};
|
||||||
|
use serde::Deserialize;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -15,6 +16,11 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub async fn get_all(headers: HeaderMap) -> Result<Response, CompositeError> {
|
||||||
|
User::authenticate(&headers)?.required()?;
|
||||||
|
Ok(Json(Tag::get_all()?).into_response())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_by_id(
|
pub async fn get_by_id(
|
||||||
Path(id): Path<Uuid>,
|
Path(id): Path<Uuid>,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
@@ -30,3 +36,15 @@ pub async fn get_by_name(
|
|||||||
User::authenticate(&headers)?.required()?;
|
User::authenticate(&headers)?.required()?;
|
||||||
Ok(Json(Tag::get_by_name(name)?).into_response())
|
Ok(Json(Tag::get_by_name(name)?).into_response())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct NewTag {
|
||||||
|
name: TagName,
|
||||||
|
}
|
||||||
|
pub async fn create(
|
||||||
|
headers: HeaderMap,
|
||||||
|
Json(form): Json<NewTag>,
|
||||||
|
) -> Result<Response, CompositeError> {
|
||||||
|
User::authenticate(&headers)?.required()?;
|
||||||
|
Ok(Json(Tag::create(form.name)?).into_response())
|
||||||
|
}
|
||||||
|
|||||||
28
src/tags.rs
28
src/tags.rs
@@ -6,6 +6,7 @@ use axum::{
|
|||||||
};
|
};
|
||||||
use rusqlite::{
|
use rusqlite::{
|
||||||
OptionalExtension, Result as RusqliteResult, ToSql,
|
OptionalExtension, Result as RusqliteResult, ToSql,
|
||||||
|
ffi::SQLITE_CONSTRAINT_UNIQUE,
|
||||||
types::{FromSql, FromSqlError, FromSqlResult, ToSqlOutput, ValueRef},
|
types::{FromSql, FromSqlError, FromSqlResult, ToSqlOutput, ValueRef},
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -20,6 +21,17 @@ pub struct Tag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Tag {
|
impl Tag {
|
||||||
|
pub fn get_all() -> Result<Vec<Tag>, TagError> {
|
||||||
|
Ok(database::conn()?
|
||||||
|
.prepare("SELECT id, tagname FROM tags")?
|
||||||
|
.query_map((), |r| {
|
||||||
|
Ok(Tag {
|
||||||
|
id: r.get(0)?,
|
||||||
|
name: r.get(1)?,
|
||||||
|
})
|
||||||
|
})?
|
||||||
|
.collect::<Result<Vec<Tag>, _>>()?)
|
||||||
|
}
|
||||||
pub fn get_by_id(id: Uuid) -> Result<Tag, TagError> {
|
pub fn get_by_id(id: Uuid) -> Result<Tag, TagError> {
|
||||||
let res = database::conn()?
|
let res = database::conn()?
|
||||||
.prepare("SELECT tagname FROM tags WHERE id = ?1")?
|
.prepare("SELECT tagname FROM tags WHERE id = ?1")?
|
||||||
@@ -50,6 +62,13 @@ impl Tag {
|
|||||||
None => Err(TagError::NoTagWithName(name)),
|
None => Err(TagError::NoTagWithName(name)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn create(name: TagName) -> Result<Tag, TagError> {
|
||||||
|
let id = Uuid::now_v7();
|
||||||
|
database::conn()?
|
||||||
|
.prepare("INSERT INTO tags(id, tagname) VALUES (?1, ?2)")?
|
||||||
|
.execute((id, &name))?;
|
||||||
|
Ok(Tag { id, name })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
@@ -60,11 +79,19 @@ pub enum TagError {
|
|||||||
NoTagWithId(Uuid),
|
NoTagWithId(Uuid),
|
||||||
#[error("No tag found with name {0}")]
|
#[error("No tag found with name {0}")]
|
||||||
NoTagWithName(TagName),
|
NoTagWithName(TagName),
|
||||||
|
#[error("A tag with this name already exists")]
|
||||||
|
TagAlreadyExists,
|
||||||
#[error("Database error: {0}")]
|
#[error("Database error: {0}")]
|
||||||
DatabaseError(#[from] DatabaseError),
|
DatabaseError(#[from] DatabaseError),
|
||||||
}
|
}
|
||||||
impl From<rusqlite::Error> for TagError {
|
impl From<rusqlite::Error> for TagError {
|
||||||
fn from(error: rusqlite::Error) -> Self {
|
fn from(error: rusqlite::Error) -> Self {
|
||||||
|
if let rusqlite::Error::SqliteFailure(e, Some(msg)) = &error
|
||||||
|
&& e.extended_code == SQLITE_CONSTRAINT_UNIQUE
|
||||||
|
&& msg.contains("tagname")
|
||||||
|
{
|
||||||
|
return TagError::TagAlreadyExists;
|
||||||
|
}
|
||||||
TagError::DatabaseError(DatabaseError::from(error))
|
TagError::DatabaseError(DatabaseError::from(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,6 +99,7 @@ impl IntoResponse for TagError {
|
|||||||
fn into_response(self) -> Response {
|
fn into_response(self) -> Response {
|
||||||
match self {
|
match self {
|
||||||
Self::DatabaseError(e) => e.into_response(),
|
Self::DatabaseError(e) => e.into_response(),
|
||||||
|
Self::TagAlreadyExists => (StatusCode::CONFLICT, self.to_string()).into_response(),
|
||||||
Self::TagNameError(_) => (StatusCode::BAD_REQUEST, self.to_string()).into_response(),
|
Self::TagNameError(_) => (StatusCode::BAD_REQUEST, self.to_string()).into_response(),
|
||||||
Self::NoTagWithId(_) => (StatusCode::BAD_REQUEST, self.to_string()).into_response(),
|
Self::NoTagWithId(_) => (StatusCode::BAD_REQUEST, self.to_string()).into_response(),
|
||||||
Self::NoTagWithName(_) => (StatusCode::BAD_REQUEST, self.to_string()).into_response(),
|
Self::NoTagWithName(_) => (StatusCode::BAD_REQUEST, self.to_string()).into_response(),
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ pub enum Permission {
|
|||||||
// All Users have the right to change their own handle
|
// All Users have the right to change their own handle
|
||||||
ChangeOthersHandles,
|
ChangeOthersHandles,
|
||||||
ManuallyCreateUsers,
|
ManuallyCreateUsers,
|
||||||
|
CreateTags,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl User {
|
impl User {
|
||||||
|
|||||||
Reference in New Issue
Block a user