Add some constraint at database level (#342)

* Add some constraint at database level

Fixes #79 and should fix #201 and #113 as well

* Fix tests

Delete duplicated data before adding constraints (only with Postgres, there is no way to do it with Sqlite with complex constraints like the one we are using)

Remove the constraint on media path

* We don't need to drop the media unique constraint anymore

Because we deleted it
This commit is contained in:
Baptiste Gelez 2018-12-09 18:44:26 +01:00 committed by GitHub
parent b73fbd3768
commit 61b6ceed92
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 568 additions and 102 deletions

View file

@ -0,0 +1,24 @@
-- This file should undo anything in `up.sql`
ALTER TABLE api_tokens DROP CONSTRAINT IF EXISTS api_tokens_unique_value;
ALTER TABLE blog_authors DROP CONSTRAINT IF EXISTS blog_author_unique;
ALTER TABLE blogs DROP CONSTRAINT IF EXISTS blog_unique;
ALTER TABLE blogs DROP CONSTRAINT IF EXISTS blog_unique_ap_url;
ALTER TABLE blogs DROP CONSTRAINT IF EXISTS blog_unique_outbox;
ALTER TABLE blogs DROP CONSTRAINT IF EXISTS blog_unique_inbox;
ALTER TABLE comments DROP CONSTRAINT IF EXISTS comments_unique_ap_url;
ALTER TABLE follows DROP CONSTRAINT IF EXISTS follows_unique_ap_url;
ALTER TABLE instances DROP CONSTRAINT IF EXISTS instance_unique_domain;
ALTER TABLE likes DROP CONSTRAINT IF EXISTS likes_unique;
ALTER TABLE likes DROP CONSTRAINT IF EXISTS likes_unique_ap_url;
ALTER TABLE mentions DROP CONSTRAINT IF EXISTS mentions_unique_ap_url;
ALTER TABLE post_authors DROP CONSTRAINT IF EXISTS post_authors_unique;
ALTER TABLE posts DROP CONSTRAINT IF EXISTS post_unique_slug;
ALTER TABLE posts DROP CONSTRAINT IF EXISTS post_unique_ap_url;
ALTER TABLE reshares DROP CONSTRAINT IF EXISTS reshares_unique;
ALTER TABLE reshares DROP CONSTRAINT IF EXISTS reshares_unique_ap_url;
ALTER TABLE tags DROP CONSTRAINT IF EXISTS tags_unique;
ALTER TABLE users DROP CONSTRAINT IF EXISTS users_unique;
ALTER TABLE users DROP CONSTRAINT IF EXISTS users_unique_inbox;
ALTER TABLE users DROP CONSTRAINT IF EXISTS users_unique_outbox;
ALTER TABLE users DROP CONSTRAINT IF EXISTS users_unique_ap_url;
ALTER TABLE users DROP CONSTRAINT IF EXISTS users_unique_followers_url;

View file

@ -0,0 +1,83 @@
-- Your SQL goes here
-- First, we delete the already duplicated data so that the constraint can be correctly applied
DELETE FROM api_tokens a USING api_tokens b WHERE
a.id > b.id
AND a.value = b.value;
DELETE FROM blog_authors a USING blog_authors b WHERE
a.id > b.id
AND a.blog_id = b.blog_id
AND a.author_id = b.author_id;
DELETE FROM blogs a USING blogs b WHERE
a.id > b.id
AND ((a.actor_id = b.actor_id AND a.instance_id = b.instance_id)
OR a.ap_url = b.ap_url
OR a.outbox_url = b.outbox_url
OR a.inbox_url = b.inbox_url);
DELETE FROM comments a USING comments b WHERE
a.id > b.id
AND (a.ap_url = b.ap_url);
DELETE FROM follows a USING follows b
WHERE a.id > b.id
AND (a.ap_url = b.ap_url);
DELETE FROM instances a USING instances b WHERE
a.id > b.id
AND (a.public_domain = b.public_domain);
DELETE FROM likes a USING likes b WHERE
a.id > b.id
AND (a.ap_url = b.ap_url
OR (a.user_id = b.user_id AND a.post_id = b.post_id));
DELETE FROM mentions a USING mentions b WHERE
a.id > b.id
AND (a.ap_url = b.ap_url);
DELETE FROM post_authors a USING post_authors b WHERE
a.id > b.id
AND a.author_id = b.author_id
AND a.post_id = b.post_id;
DELETE FROM posts a USING posts b WHERE
a.id > b.id
AND ((a.ap_url = b.ap_url)
OR (a.blog_id = b.blog_id AND a.slug = b.slug));
DELETE FROM reshares a USING reshares b WHERE
a.id > b.id
AND (a.ap_url = b.ap_url
OR (a.user_id = b.user_id AND a.post_id = b.post_id));
DELETE FROM tags a USING tags b WHERE
a.id > b.id
AND a.tag = b.tag
AND a.post_id = b.post_id
AND a.is_hashtag = b.is_hashtag;
DELETE FROM users a USING users b WHERE
a.id > b.id
AND (a.ap_url = b.ap_url
OR (a.username = b.username AND a.instance_id = b.instance_id)
OR a.outbox_url = b.outbox_url
OR a.inbox_url = b.inbox_url
OR a.followers_endpoint = b.followers_endpoint);
-- Then we add the UNIQUE constraints
ALTER TABLE api_tokens ADD CONSTRAINT api_tokens_unique_value UNIQUE (value);
ALTER TABLE blog_authors ADD CONSTRAINT blog_author_unique UNIQUE (blog_id, author_id);
ALTER TABLE blogs ADD CONSTRAINT blog_unique UNIQUE (actor_id, instance_id);
ALTER TABLE blogs ADD CONSTRAINT blog_unique_ap_url UNIQUE (ap_url);
ALTER TABLE blogs ADD CONSTRAINT blog_unique_outbox UNIQUE (outbox_url);
ALTER TABLE blogs ADD CONSTRAINT blog_unique_inbox UNIQUE (inbox_url);
ALTER TABLE comments ADD CONSTRAINT comments_unique_ap_url UNIQUE (ap_url);
ALTER TABLE follows ADD CONSTRAINT follows_unique_ap_url UNIQUE (ap_url);
ALTER TABLE instances ADD CONSTRAINT instance_unique_domain UNIQUE (public_domain);
ALTER TABLE likes ADD CONSTRAINT likes_unique UNIQUE (user_id, post_id);
ALTER TABLE likes ADD CONSTRAINT likes_unique_ap_url UNIQUE (ap_url);
ALTER TABLE mentions ADD CONSTRAINT mentions_unique_ap_url UNIQUE (ap_url);
ALTER TABLE post_authors ADD CONSTRAINT post_authors_unique UNIQUE (post_id, author_id);
ALTER TABLE posts ADD CONSTRAINT post_unique_slug UNIQUE (blog_id, slug);
ALTER TABLE posts ADD CONSTRAINT post_unique_ap_url UNIQUE (ap_url);
ALTER TABLE reshares ADD CONSTRAINT reshares_unique UNIQUE (user_id, post_id);
ALTER TABLE reshares ADD CONSTRAINT reshares_unique_ap_url UNIQUE (ap_url);
ALTER TABLE tags ADD CONSTRAINT tags_unique UNIQUE (tag, post_id, is_hashtag);
ALTER TABLE users ADD CONSTRAINT users_unique UNIQUE (username, instance_id);
ALTER TABLE users ADD CONSTRAINT users_unique_inbox UNIQUE (inbox_url);
ALTER TABLE users ADD CONSTRAINT users_unique_outbox UNIQUE (outbox_url);
ALTER TABLE users ADD CONSTRAINT users_unique_ap_url UNIQUE (ap_url);
ALTER TABLE users ADD CONSTRAINT users_unique_followers_url UNIQUE (followers_endpoint);

View file

@ -0,0 +1,178 @@
-- This file should undo anything in `up.sql`
CREATE TABLE api_tokens2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
value TEXT NOT NULL,
scopes TEXT NOT NULL,
app_id INTEGER NOT NULL REFERENCES apps(id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE
);
INSERT INTO api_tokens2 SELECT * FROM api_tokens;
DROP TABLE api_tokens;
ALTER TABLE api_tokens2 RENAME TO api_tokens;
CREATE TABLE blog_authors2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
blog_id INTEGER REFERENCES blogs(id) ON DELETE CASCADE NOT NULL,
author_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL,
is_owner BOOLEAN NOT NULL DEFAULT 'f'
);
INSERT INTO blog_authors2 SELECT * FROM blog_authors;
DROP TABLE blog_authors;
ALTER TABLE blog_authors2 RENAME TO blog_authors;
CREATE TABLE blogs2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
actor_id VARCHAR NOT NULL,
title VARCHAR NOT NULL,
summary TEXT NOT NULL DEFAULT '',
outbox_url VARCHAR NOT NULL,
inbox_url VARCHAR NOT NULL,
instance_id INTEGER REFERENCES instances(id) ON DELETE CASCADE NOT NULL,
creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
ap_url text not null default '',
private_key TEXT,
public_key TEXT NOT NULL DEFAULT ''
)
INSERT INTO blogs2 SELECT * FROM blogs;
DROP TABLE blogs;
ALTER TABLE blogs2 RENAME TO blogs;
CREATE TABLE comments2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
content TEXT NOT NULL DEFAULT '',
in_response_to_id INTEGER REFERENCES comments(id),
post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE NOT NULL,
author_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL,
creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
ap_url VARCHAR,
sensitive BOOLEAN NOT NULL DEFAULT 'f',
spoiler_text TEXT NOT NULL DEFAULT ''
);
INSERT INTO comments2 SELECT * FROM comments;
DROP TABLE comments;
ALTER TABLE comments2 RENAME TO comments;
CREATE TABLE follows2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
follower_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL,
following_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL,
ap_url TEXT NOT NULL default ''
);
INSERT INTO follows2 SELECT * FROM follows;
DROP TABLE follows;
ALTER TABLE follows2 RENAME TO follows;
CREATE TABLE instances2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
public_domain VARCHAR NOT NULL,
name VARCHAR NOT NULL,
local BOOLEAN NOT NULL DEFAULT 'f',
blocked BOOLEAN NOT NULL DEFAULT 'f',
creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
open_registrations BOOLEAN NOT NULL DEFAULT 't',
short_description TEXT NOT NULL DEFAULT '',
long_description TEXT NOT NULL DEFAULT '',
default_license TEXT NOT NULL DEFAULT 'CC-BY-SA',
long_description_html VARCHAR NOT NULL DEFAULT '',
short_description_html VARCHAR NOT NULL DEFAULT ''
);
INSERT INTO instances2 SELECT * FROM instances;
DROP TABLE instances;
ALTER TABLE instances2 RENAME TO instances;
CREATE TABLE likes2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL,
post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE NOT NULL,
creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
ap_url VARCHAR NOT NULL default ''
);
INSERT INTO likes2 SELECT * FROM likes;
DROP TABLE likes;
ALTER TABLE likes2 RENAME TO likes;
CREATE TABLE mentions2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
mentioned_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL,
post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE,
comment_id INTEGER REFERENCES comments(id) ON DELETE CASCADE,
ap_url VARCHAR NOT NULL DEFAULT ''
);
INSERT INTO mentions2 SELECT * FROM mentions;
DROP TABLE mentions;
ALTER TABLE mentions2 RENAME TO mentions;
CREATE TABLE post_authors2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE NOT NULL,
author_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL
)
INSERT INTO post_authors2 SELECT * FROM post_authors;
DROP TABLE post_authors;
ALTER TABLE post_authors2 RENAME TO post_authors;
CREATE TABLE posts2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
blog_id INTEGER REFERENCES blogs(id) ON DELETE CASCADE NOT NULL,
slug VARCHAR NOT NULL,
title VARCHAR NOT NULL,
content TEXT NOT NULL DEFAULT '',
published BOOLEAN NOT NULL DEFAULT 'f',
license VARCHAR NOT NULL DEFAULT 'CC-BY-SA',
creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
ap_url VARCHAR NOT NULL DEFAULT '',
subtitle TEXT NOT NULL DEFAULT '',
source TEXT NOT NULL DEFAULT ''
);
INSERT INTO posts2 SELECT * FROM posts;
DROP TABLE posts;
ALTER TABLE posts2 RENAME TO posts;
CREATE TABLE tags2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
tag TEXT NOT NULL DEFAULT '',
is_hashtag BOOLEAN NOT NULL DEFAULT 'f',
post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE NOT NULL
);
INSERT INTO tags2 SELECT * FROM tags;
DROP TABLE tags;
ALTER TABLE tags2 RENAME TO tags;
CREATE TABLE users (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
username VARCHAR NOT NULL,
display_name VARCHAR NOT NULL DEFAULT '',
outbox_url VARCHAR NOT NULL,
inbox_url VARCHAR NOT NULL,
is_admin BOOLEAN NOT NULL DEFAULT 'f',
summary TEXT NOT NULL DEFAULT '',
email TEXT,
hashed_password TEXT,
instance_id INTEGER REFERENCES instances(id) ON DELETE CASCADE NOT NULL,
creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
ap_url TEXT NOT NULL default '',
private_key TEXT,
public_key TEXT NOT NULL DEFAULT '',
shared_inbox_url VARCHAR,
followers_endpoint VARCHAR NOT NULL DEFAULT '',
avatar_id INTEGER REFERENCES medias(id) ON DELETE CASCADE,
last_fetched_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (avatar_id) REFERENCES medias(id) ON DELETE SET NULL
);
INSERT INTO users2 SELECT * FROM users;
DROP TABLE users;
ALTER TABLE users2 RENAME TO users;

View file

@ -0,0 +1,186 @@
-- Your SQL goes here
CREATE TABLE api_tokens2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
value TEXT NOT NULL UNIQUE,
scopes TEXT NOT NULL,
app_id INTEGER NOT NULL REFERENCES apps(id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE
);
INSERT INTO api_tokens2 SELECT * FROM api_tokens;
DROP TABLE api_tokens;
ALTER TABLE api_tokens2 RENAME TO api_tokens;
CREATE TABLE blog_authors2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
blog_id INTEGER REFERENCES blogs(id) ON DELETE CASCADE NOT NULL,
author_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL,
is_owner BOOLEAN NOT NULL DEFAULT 'f',
CONSTRAINT blog_authors_unique UNIQUE (blog_id, author_id)
);
INSERT INTO blog_authors2 SELECT * FROM blog_authors;
DROP TABLE blog_authors;
ALTER TABLE blog_authors2 RENAME TO blog_authors;
CREATE TABLE blogs2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
actor_id VARCHAR NOT NULL,
title VARCHAR NOT NULL,
summary TEXT NOT NULL DEFAULT '',
outbox_url VARCHAR NOT NULL UNIQUE,
inbox_url VARCHAR NOT NULL UNIQUE,
instance_id INTEGER REFERENCES instances(id) ON DELETE CASCADE NOT NULL,
creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
ap_url text not null default '' UNIQUE,
private_key TEXT,
public_key TEXT NOT NULL DEFAULT '',
CONSTRAINT blog_unique UNIQUE (actor_id, instance_id)
);
INSERT INTO blogs2 SELECT * FROM blogs;
DROP TABLE blogs;
ALTER TABLE blogs2 RENAME TO blogs;
CREATE TABLE comments2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
content TEXT NOT NULL DEFAULT '',
in_response_to_id INTEGER REFERENCES comments(id),
post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE NOT NULL,
author_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL,
creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
ap_url VARCHAR UNIQUE,
sensitive BOOLEAN NOT NULL DEFAULT 'f',
spoiler_text TEXT NOT NULL DEFAULT ''
);
INSERT INTO comments2 SELECT * FROM comments;
DROP TABLE comments;
ALTER TABLE comments2 RENAME TO comments;
CREATE TABLE follows2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
follower_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL,
following_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL,
ap_url TEXT NOT NULL default '' UNIQUE
);
INSERT INTO follows2 SELECT * FROM follows;
DROP TABLE follows;
ALTER TABLE follows2 RENAME TO follows;
CREATE TABLE instances2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
public_domain VARCHAR NOT NULL UNIQUE,
name VARCHAR NOT NULL,
local BOOLEAN NOT NULL DEFAULT 'f',
blocked BOOLEAN NOT NULL DEFAULT 'f',
creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
open_registrations BOOLEAN NOT NULL DEFAULT 't',
short_description TEXT NOT NULL DEFAULT '',
long_description TEXT NOT NULL DEFAULT '',
default_license TEXT NOT NULL DEFAULT 'CC-BY-SA',
long_description_html VARCHAR NOT NULL DEFAULT '',
short_description_html VARCHAR NOT NULL DEFAULT ''
);
INSERT INTO instances2 SELECT * FROM instances;
DROP TABLE instances;
ALTER TABLE instances2 RENAME TO instances;
CREATE TABLE likes2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL,
post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE NOT NULL,
creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
ap_url VARCHAR NOT NULL default '' UNIQUE,
CONSTRAINT likes_unique UNIQUE (user_id, post_id)
);
INSERT INTO likes2 SELECT * FROM likes;
DROP TABLE likes;
ALTER TABLE likes2 RENAME TO likes;
CREATE TABLE mentions2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
mentioned_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL,
post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE,
comment_id INTEGER REFERENCES comments(id) ON DELETE CASCADE,
ap_url VARCHAR NOT NULL DEFAULT '' UNIQUE
);
INSERT INTO mentions2 SELECT * FROM mentions;
DROP TABLE mentions;
ALTER TABLE mentions2 RENAME TO mentions;
CREATE TABLE post_authors2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE NOT NULL,
author_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL,
CONSTRAINT blog_authors_unique UNIQUE (post_id, author_id)
);
INSERT INTO post_authors2 SELECT * FROM post_authors;
DROP TABLE post_authors;
ALTER TABLE post_authors2 RENAME TO post_authors;
CREATE TABLE posts2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
blog_id INTEGER REFERENCES blogs(id) ON DELETE CASCADE NOT NULL,
slug VARCHAR NOT NULL,
title VARCHAR NOT NULL,
content TEXT NOT NULL DEFAULT '',
published BOOLEAN NOT NULL DEFAULT 'f',
license VARCHAR NOT NULL DEFAULT 'CC-BY-SA',
creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
ap_url VARCHAR NOT NULL DEFAULT '' UNIQUE,
subtitle TEXT NOT NULL DEFAULT '',
source TEXT NOT NULL DEFAULT '',
cover_id INTEGER REFERENCES medias(id) DEFAULT NULL,
CONSTRAINT blog_authors_unique UNIQUE (blog_id, slug)
);
INSERT INTO posts2 SELECT * FROM posts;
DROP TABLE posts;
ALTER TABLE posts2 RENAME TO posts;
CREATE TABLE tags2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
tag TEXT NOT NULL DEFAULT '',
is_hashtag BOOLEAN NOT NULL DEFAULT 'f',
post_id INTEGER REFERENCES posts(id) ON DELETE CASCADE NOT NULL,
CONSTRAINT blog_authors_unique UNIQUE (tag, is_hashtag, post_id)
);
INSERT INTO tags2 SELECT * FROM tags;
DROP TABLE tags;
ALTER TABLE tags2 RENAME TO tags;
CREATE TABLE users2 (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
username VARCHAR NOT NULL,
display_name VARCHAR NOT NULL DEFAULT '',
outbox_url VARCHAR NOT NULL UNIQUE,
inbox_url VARCHAR NOT NULL UNIQUE,
is_admin BOOLEAN NOT NULL DEFAULT 'f',
summary TEXT NOT NULL DEFAULT '',
email TEXT,
hashed_password TEXT,
instance_id INTEGER REFERENCES instances(id) ON DELETE CASCADE NOT NULL,
creation_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
ap_url TEXT NOT NULL default '' UNIQUE,
private_key TEXT,
public_key TEXT NOT NULL DEFAULT '',
shared_inbox_url VARCHAR,
followers_endpoint VARCHAR NOT NULL DEFAULT '' UNIQUE,
avatar_id INTEGER REFERENCES medias(id) ON DELETE CASCADE,
last_fetched_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (avatar_id) REFERENCES medias(id) ON DELETE SET NULL,
CONSTRAINT blog_authors_unique UNIQUE (username, instance_id)
);
INSERT INTO users2 SELECT * FROM users;
DROP TABLE users;
ALTER TABLE users2 RENAME TO users;

View file

@ -513,36 +513,35 @@ pub(crate) mod tests {
use search::tests::get_searcher;
use Connection as Conn;
pub(crate) fn fill_database(conn: &Conn) -> Vec<Blog> {
pub(crate) fn fill_database(conn: &Conn) -> (Vec<User>, Vec<Blog>) {
instance_tests::fill_database(conn);
let users = usersTests::fill_database(conn);
let blogs = vec![
NewBlog::new_local(
"BlogName".to_owned(),
"Blog name".to_owned(),
"This is a small blog".to_owned(),
Instance::local_id(conn),
),
NewBlog::new_local(
let blog1 = Blog::insert(conn, NewBlog::new_local(
"BlogName".to_owned(),
"Blog name".to_owned(),
"This is a small blog".to_owned(),
Instance::local_id(conn),
));
blog1.update_boxes(conn);
let blog2 = Blog::insert(conn, NewBlog::new_local(
"MyBlog".to_owned(),
"My blog".to_owned(),
"Welcome to my blog".to_owned(),
Instance::local_id(conn),
),
NewBlog::new_local(
));
blog2.update_boxes(conn);
let blog3 = Blog::insert(conn, NewBlog::new_local(
"WhyILikePlume".to_owned(),
"Why I like Plume".to_owned(),
"In this blog I will explay you why I like Plume so much".to_owned(),
Instance::local_id(conn),
),
].into_iter()
.map(|nb| Blog::insert(conn, nb))
.collect::<Vec<_>>();
));
blog3.update_boxes(conn);
BlogAuthor::insert(
conn,
NewBlogAuthor {
blog_id: blogs[0].id,
blog_id: blog1.id,
author_id: users[0].id,
is_owner: true,
},
@ -551,7 +550,7 @@ pub(crate) mod tests {
BlogAuthor::insert(
conn,
NewBlogAuthor {
blog_id: blogs[0].id,
blog_id: blog1.id,
author_id: users[1].id,
is_owner: false,
},
@ -560,7 +559,7 @@ pub(crate) mod tests {
BlogAuthor::insert(
conn,
NewBlogAuthor {
blog_id: blogs[1].id,
blog_id: blog2.id,
author_id: users[1].id,
is_owner: true,
},
@ -569,12 +568,12 @@ pub(crate) mod tests {
BlogAuthor::insert(
conn,
NewBlogAuthor {
blog_id: blogs[2].id,
blog_id: blog3.id,
author_id: users[2].id,
is_owner: true,
},
);
blogs
(users, vec![ blog1, blog2, blog3 ])
}
#[test]
@ -604,29 +603,29 @@ pub(crate) mod tests {
fn authors() {
let conn = &db();
conn.test_transaction::<_, (), _>(|| {
let user = usersTests::fill_database(conn);
fill_database(conn);
let (user, _) = fill_database(conn);
let blog = vec![
Blog::insert(
conn,
NewBlog::new_local(
"SomeName".to_owned(),
"Some name".to_owned(),
"This is some blog".to_owned(),
Instance::local_id(conn),
),
let b1 = Blog::insert(
conn,
NewBlog::new_local(
"SomeName".to_owned(),
"Some name".to_owned(),
"This is some blog".to_owned(),
Instance::local_id(conn),
),
Blog::insert(
conn,
NewBlog::new_local(
"Blog".to_owned(),
"Blog".to_owned(),
"I've named my blog Blog".to_owned(),
Instance::local_id(conn),
),
);
b1.update_boxes(conn);
let b2 = Blog::insert(
conn,
NewBlog::new_local(
"Blog".to_owned(),
"Blog".to_owned(),
"I've named my blog Blog".to_owned(),
Instance::local_id(conn),
),
];
);
b2.update_boxes(conn);
let blog = vec![ b1, b2 ];
BlogAuthor::insert(
conn,
@ -756,7 +755,7 @@ pub(crate) mod tests {
fn delete() {
let conn = &db();
conn.test_transaction::<_, (), _>(|| {
let blogs = fill_database(conn);
let (_, blogs) = fill_database(conn);
blogs[0].delete(conn, &get_searcher());
assert!(Blog::get(conn, blogs[0].id).is_none());
@ -770,29 +769,29 @@ pub(crate) mod tests {
let conn = &db();
conn.test_transaction::<_, (), _>(|| {
let searcher = get_searcher();
let user = usersTests::fill_database(conn);
fill_database(conn);
let (user, _) = fill_database(conn);
let blog = vec![
Blog::insert(
conn,
NewBlog::new_local(
"SomeName".to_owned(),
"Some name".to_owned(),
"This is some blog".to_owned(),
Instance::local_id(conn),
),
let b1 = Blog::insert(
conn,
NewBlog::new_local(
"SomeName".to_owned(),
"Some name".to_owned(),
"This is some blog".to_owned(),
Instance::local_id(conn),
),
Blog::insert(
conn,
NewBlog::new_local(
"Blog".to_owned(),
"Blog".to_owned(),
"I've named my blog Blog".to_owned(),
Instance::local_id(conn),
),
);
b1.update_boxes(conn);
let b2 = Blog::insert(
conn,
NewBlog::new_local(
"Blog".to_owned(),
"Blog".to_owned(),
"I've named my blog Blog".to_owned(),
Instance::local_id(conn),
),
];
);
b2.update_boxes(conn);
let blog = vec![ b1, b2 ];
BlogAuthor::insert(
conn,

View file

@ -220,7 +220,7 @@ pub(crate) mod tests {
use users::tests as usersTests;
use Connection as Conn;
pub(crate) fn fill_database(conn: &Conn) -> Vec<Media> {
pub(crate) fn fill_database(conn: &Conn) -> (Vec<User>, Vec<Media>) {
let mut wd = current_dir().unwrap().to_path_buf();
while wd.pop() {
if wd.join(".git").exists() {
@ -236,7 +236,7 @@ pub(crate) mod tests {
let f2 = "static/media/2.mp3".to_owned();
fs::write(f1.clone(), []).unwrap();
fs::write(f2.clone(), []).unwrap();
vec![
(users, vec![
NewMedia {
file_path: f1,
alt_text: "some alt".to_owned(),
@ -266,7 +266,7 @@ pub(crate) mod tests {
},
].into_iter()
.map(|nm| Media::insert(conn, nm))
.collect()
.collect())
}
pub(crate) fn clean(conn: &Conn) {
@ -282,8 +282,7 @@ pub(crate) mod tests {
fn delete() {
let conn = &db();
conn.test_transaction::<_, (), _>(|| {
let user = usersTests::fill_database(conn)[0].id;
fill_database(conn);
let user = fill_database(conn).0[0].id;
let path = "static/media/test_deletion".to_owned();
fs::write(path.clone(), []).unwrap();
@ -316,10 +315,9 @@ pub(crate) mod tests {
fn set_owner() {
let conn = &db();
conn.test_transaction::<_, (), _>(|| {
let users = usersTests::fill_database(conn);
let (users, _) = fill_database(conn);
let u1 = &users[0];
let u2 = &users[1];
fill_database(conn);
let path = "static/media/test_set_owner".to_owned();
fs::write(path.clone(), []).unwrap();

View file

@ -117,7 +117,7 @@ pub(crate) mod tests {
let conn = &db();
conn.test_transaction::<_, (), _>(|| {
let searcher = get_searcher();
let blog = &fill_database(conn)[0];
let blog = &fill_database(conn).1[0];
let author = &blog.list_authors(conn)[0];
let title = random_hex()[..8].to_owned();

View file

@ -998,39 +998,37 @@ pub(crate) mod tests {
pub(crate) fn fill_database(conn: &Conn) -> Vec<User> {
instance_tests::fill_database(conn);
let local_user = vec![
NewUser::new_local(
conn,
"admin".to_owned(),
"The admin".to_owned(),
true,
"Hello there, I'm the admin",
"admin@example.com".to_owned(),
"invalid_admin_password".to_owned(),
),
NewUser::new_local(
conn,
"user".to_owned(),
"Some user".to_owned(),
false,
"Hello there, I'm no one",
"user@example.com".to_owned(),
"invalid_user_password".to_owned(),
),
NewUser::new_local(
conn,
"other".to_owned(),
"Another user".to_owned(),
false,
"Hello there, I'm someone else",
"other@example.com".to_owned(),
"invalid_other_password".to_owned(),
),
];
for u in local_user.iter() {
u.update_boxes(conn);
}
local_user
let admin = NewUser::new_local(
conn,
"admin".to_owned(),
"The admin".to_owned(),
true,
"Hello there, I'm the admin",
"admin@example.com".to_owned(),
"invalid_admin_password".to_owned(),
);
admin.update_boxes(conn);
let user = NewUser::new_local(
conn,
"user".to_owned(),
"Some user".to_owned(),
false,
"Hello there, I'm no one",
"user@example.com".to_owned(),
"invalid_user_password".to_owned(),
);
user.update_boxes(conn);
let other = NewUser::new_local(
conn,
"other".to_owned(),
"Another user".to_owned(),
false,
"Hello there, I'm someone else",
"other@example.com".to_owned(),
"invalid_other_password".to_owned(),
);
other.update_boxes(conn);
vec![ admin, user, other ]
}
#[test]