Skip to content
This repository has been archived by the owner on Sep 2, 2021. It is now read-only.

Commit

Permalink
Add basic implementation for the tags endpoint.
Browse files Browse the repository at this point in the history
  • Loading branch information
farodin91 committed Oct 12, 2016
1 parent 5cea7f2 commit fdecdec
Show file tree
Hide file tree
Showing 8 changed files with 263 additions and 0 deletions.
1 change: 1 addition & 0 deletions migrations/001_prerelease/down.sql
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ DROP TABLE room_aliases;
DROP TABLE room_memberships;
DROP TABLE rooms;
DROP TABLE users;
DROP TABLE room_tags;
9 changes: 9 additions & 0 deletions migrations/001_prerelease/up.sql
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,12 @@ CREATE TABLE users (
created_at TIMESTAMP NOT NULL DEFAULT now(),
updated_at TIMESTAMP NOT NULL DEFAULT now()
);

CREATE TABLE room_tags(
id BIGSERIAL PRIMARY KEY,
user_id TEXT NOT NULL,
room_id TEXT NOT NULL,
tag TEXT NOT NULL,
content TEXT NOT NULL,
UNIQUE (user_id, room_id, tag)
);
2 changes: 2 additions & 0 deletions src/api/r0/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub use self::logout::Logout;
pub use self::members::Members;
pub use self::registration::Register;
pub use self::room_creation::CreateRoom;
pub use self::tags::{DeleteTag, GetTags, PutTag};
pub use self::versions::Versions;

mod account;
Expand All @@ -25,4 +26,5 @@ mod logout;
mod members;
mod registration;
mod room_creation;
mod tags;
mod versions;
171 changes: 171 additions & 0 deletions src/api/r0/tags.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
//! Endpoints for tags.
use iron::{Chain, Handler, IronResult, Request, Response};
use iron::status::Status;
use router::Router;
use std::io::Read;

use db::DB;
use error::ApiError;
use middleware::{AccessTokenAuth, JsonRequest, RoomIdParam, UserIdParam};
use modifier::SerializableResponse;
use tags::RoomTag;

/// The `/user/:user_id/rooms/:room_id/tags` endpoint.
pub struct GetTags;

#[derive(Debug, Serialize)]
struct GetTagsResponse {
tags: Vec<RoomTag>,
}

impl GetTags {
/// Create a `GetTags` with all necessary middleware.
pub fn chain() -> Chain {
let mut chain = Chain::new(GetTags);

chain.link_before(JsonRequest);
chain.link_before(UserIdParam);
chain.link_before(RoomIdParam);
chain.link_before(AccessTokenAuth);

chain
}
}

impl Handler for GetTags {
fn handle(&self, request: &mut Request) -> IronResult<Response> {
let user_id = request.extensions.get::<UserIdParam>()
.expect("UserIdParam should ensure a UserId").clone();
let room_id = request.extensions.get::<RoomIdParam>()
.expect("RoomIdParam should ensure a RoomId").clone();

let connection = DB::from_request(request)?;

let tags = RoomTag::find(&connection, user_id, room_id)?;

let response = GetTagsResponse { tags: tags };

Ok(Response::with((Status::Ok, SerializableResponse(response))))
}
}

/// The `/user/:user_id/rooms/:room_id/tags/:tag` endpoint.
pub struct PutTag;

impl PutTag {
/// Create a `GetTags` with all necessary middleware.
pub fn chain() -> Chain {
let mut chain = Chain::new(PutTag);

chain.link_before(JsonRequest);
chain.link_before(UserIdParam);
chain.link_before(RoomIdParam);
chain.link_before(AccessTokenAuth);

chain
}
}

impl Handler for PutTag {
fn handle(&self, request: &mut Request) -> IronResult<Response> {
let user_id = request.extensions.get::<UserIdParam>()
.expect("UserIdParam should ensure a UserId").clone();
let room_id = request.extensions.get::<RoomIdParam>()
.expect("RoomIdParam should ensure a RoomId").clone();
let params = request.extensions.get::<Router>().expect("Params object is missing").clone();
let tag = match params.find("tag") {
Some(tag) => Ok(String::from(tag)),
None => {
Err(ApiError::missing_param("tag"))
}
}?;

let mut content = String::new();
if let Err(_) = request.body.read_to_string(&mut content) {
Err(ApiError::not_found(None))?;
}

let connection = DB::from_request(request)?;

RoomTag::upsert(&connection, user_id, room_id, tag, content)?;

Ok(Response::with(Status::Ok))
}
}

/// The `/user/:user_id/rooms/:room_id/tags/:tag` endpoint.
pub struct DeleteTag;

impl DeleteTag {
/// Create a `GetTags` with all necessary middleware.
pub fn chain() -> Chain {
let mut chain = Chain::new(DeleteTag);

chain.link_before(JsonRequest);
chain.link_before(UserIdParam);
chain.link_before(RoomIdParam);
chain.link_before(AccessTokenAuth);

chain
}
}

impl Handler for DeleteTag {
fn handle(&self, request: &mut Request) -> IronResult<Response> {
let user_id = request.extensions.get::<UserIdParam>()
.expect("UserIdParam should ensure a UserId").clone();
let room_id = request.extensions.get::<RoomIdParam>()
.expect("RoomIdParam should ensure a RoomId").clone();
let params = request.extensions.get::<Router>().expect("Params object is missing").clone();
let tag = match params.find("tag") {
Some(tag) => Ok(String::from(tag)),
None => {
Err(ApiError::missing_param("tag"))
}
}?;

let connection = DB::from_request(request)?;

RoomTag::delete(&connection, user_id, room_id, tag)?;

Ok(Response::with(Status::Ok))
}
}


#[cfg(test)]
mod tests {
use test::Test;
use iron::status::Status;

#[test]
fn get_tag() {
let test = Test::new();
let access_token = test.create_access_token(); // @carl:ruma.test

let room_id = test.create_public_room(&access_token);

let put_tag_path = format!(
"/_matrix/client/r0/user/@carl:ruma.test/rooms/{}/tags/work?access_token={}",
room_id,
access_token
);

let response = test.put(&put_tag_path, r"{}");
assert_eq!(response.status, Status::Ok);

let get_tag_path = format!(
"/_matrix/client/r0/user/@carl:ruma.test/rooms/{}/tags?access_token={}",
room_id,
access_token
);

let response = test.get(&get_tag_path);
assert_eq!(response.status, Status::Ok);
let chunk = response.json().find("tags").unwrap();
assert!(chunk.is_array());
let chunk = chunk.as_array().unwrap();
assert_eq!(chunk.len(), 1);
}
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ pub mod schema;
pub mod server;
pub mod swagger;
pub mod room_membership;
pub mod tags;
#[cfg(test)] pub mod test;
pub mod user;

Expand Down
10 changes: 10 additions & 0 deletions src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,13 @@ table! {
content -> Text,
}
}

table! {
room_tags {
id -> BigSerial,
user_id -> Text,
room_id -> Text,
tag -> Text,
content -> Text,
}
}
6 changes: 6 additions & 0 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@ use api::r0::{
CreateRoom,
DeactivateAccount,
DeleteRoomAlias,
DeleteTag,
GetRoomAlias,
GetTags,
JoinRoom,
Login,
Logout,
Members,
PutAccountData,
PutRoomAccountData,
PutRoomAlias,
PutTag,
Register,
SendMessageEvent,
StateMessageEvent,
Expand Down Expand Up @@ -82,6 +85,9 @@ impl<'a> Server<'a> {
);
r0_router.post("/rooms/:room_id/join", JoinRoom::chain());
r0_router.get("/rooms/:room_id/members", Members::chain());
r0_router.get("/user/:user_id/rooms/:room_id/tags", GetTags::chain());
r0_router.put("/user/:user_id/rooms/:room_id/tags/:tag", PutTag::chain());
r0_router.delete("/user/:user_id/rooms/:room_id/tags/:tag", DeleteTag::chain());

let mut r0 = Chain::new(r0_router);

Expand Down
63 changes: 63 additions & 0 deletions src/tags.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@

use diesel::{
Connection,
ExpressionMethods,
ExecuteDsl,
LoadDsl,
FilterDsl,
SelectDsl,
insert,
};
use diesel::pg::PgConnection;
use ruma_identifiers::{RoomId, UserId};

use error::ApiError;
use schema::room_tags;

/// A Matrix room membership.
#[derive(Debug, Clone, Serialize, Queryable)]
#[changeset_for(room_tags)]
pub struct RoomTag {
/// The user's ID.
pub user_id: UserId,
/// The room's ID.
pub room_id: RoomId,
/// Tag
pub tag: String,
/// Json content
pub content: String,
}


impl RoomTag {

/// Return `RoomTag` for given `UserId` and `RoomId`.
pub fn find(
connection: &PgConnection,
user_id: UserId,
room_id: RoomId)
-> Result<Vec<RoomTag>, ApiError> {

Ok(vec![])
}

pub fn upsert(
connection: &PgConnection,
user_id: UserId,
room_id: RoomId,
tag: String,
content: String)
-> Result<(), ApiError> {

Ok(())
}

pub fn delete(
connection: &PgConnection,
user_id: UserId,
room_id: RoomId,
tag: String)
-> Result<(), ApiError> {
Ok(())
}
}

0 comments on commit fdecdec

Please sign in to comment.