Allow multiple identities (accounts actors) for one user.

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
master
Thomas Citharel 4 years ago
parent a71b81af91
commit dee437e4f3
  1. 12
      js/src/App.vue
  2. 8
      js/src/auth/index.js
  3. 10
      js/src/components/Account/Account.vue
  4. 3
      js/src/components/Account/Login.vue
  5. 9
      js/src/components/Account/Validate.vue
  6. 4
      js/src/components/Event/Create.vue
  7. 8
      js/src/components/Event/Event.vue
  8. 2
      js/src/components/Group/Group.vue
  9. 10
      js/src/components/Home.vue
  10. 8
      js/src/components/NavBar.vue
  11. 37
      js/src/main.js
  12. 22
      js/src/store/index.js
  13. 1
      js/src/store/mutation-types.js
  14. 4
      lib/eventos/actors/actor.ex
  15. 6
      lib/eventos/actors/actors.ex
  16. 5
      lib/eventos/actors/service/activation.ex
  17. 4
      lib/eventos/actors/user.ex
  18. 2
      lib/eventos_web/controllers/group_controller.ex
  19. 2
      lib/eventos_web/controllers/user_controller.ex
  20. 4
      lib/eventos_web/views/actor_view.ex
  21. 4
      lib/eventos_web/views/event_view.ex
  22. 2
      lib/eventos_web/views/group_view.ex
  23. 4
      lib/eventos_web/views/member_view.ex
  24. 2
      lib/eventos_web/views/search_view.ex
  25. 4
      lib/eventos_web/views/user_view.ex
  26. 23
      priv/repo/migrations/20180709154152_allow_multiple_accounts_for_user.exs
  27. 5
      priv/static/css/app.a3c38b40a31fa078b9acdba649983cb5.css
  28. BIN
      priv/static/img/oh_no.d61c172.jpg
  29. 2
      priv/static/js/app.29c4f33994925affb616.js
  30. 1
      priv/static/js/app.29c4f33994925affb616.js.map
  31. 2
      priv/static/js/manifest.881ff1dba0c9e5d0130f.js
  32. 1
      priv/static/js/manifest.881ff1dba0c9e5d0130f.js.map
  33. 18
      priv/static/js/vendor.0d63a19c6680451dd336.js
  34. 1
      priv/static/js/vendor.0d63a19c6680451dd336.js.map
  35. 15
      test/eventos_web/controllers/actor_controller_test.exs
  36. 4
      test/eventos_web/controllers/address_controller_test.exs
  37. 4
      test/eventos_web/controllers/bot_controller_test.exs
  38. 4
      test/eventos_web/controllers/category_controller_test.exs
  39. 12
      test/eventos_web/controllers/comment_controller_test.exs
  40. 22
      test/eventos_web/controllers/event_controller_test.exs
  41. 4
      test/eventos_web/controllers/session_controller_test.exs
  42. 4
      test/eventos_web/controllers/tag_controller_test.exs
  43. 4
      test/eventos_web/controllers/track_controller_test.exs
  44. 4
      test/eventos_web/controllers/user_controller_test.exs
  45. 4
      test/support/factory.ex

@ -12,24 +12,24 @@
<v-list-group
value="false"
>
<v-list-tile avatar v-if="$store.state.user" slot="activator">
<v-list-tile avatar v-if="$store.state.actor" slot="activator">
<v-list-tile-avatar>
<img v-if="!getUser().actor.avatar_url"
<img v-if="!$store.state.actor.avatar"
class="img-circle elevation-7 mb-1"
src="https://picsum.photos/125/125/"
>
<img v-else
class="img-circle elevation-7 mb-1"
:src="getUser().actor.avatar_url"
:src="$store.state.actor.avatar"
>
</v-list-tile-avatar>
<v-list-tile-content @click="$router.push({name: 'Account', params: { name: getUser().actor.username }})">
<v-list-tile-content @click="$router.push({name: 'Account', params: { name: $store.state.actor.username }})">
<v-list-tile-title>{{ this.displayed_name }}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-list-tile avatar v-if="$store.state.user">
<v-list-tile avatar v-if="$store.state.actor">
<v-list-tile-avatar>
<img
class="img-circle elevation-7 mb-1"
@ -177,7 +177,7 @@ export default {
},
computed: {
displayed_name() {
return this.$store.state.user.actor.display_name === null ? this.$store.state.user.actor.username : this.$store.state.user.actor.display_name
return this.$store.state.actor.display_name === null ? this.$store.state.actor.username : this.$store.state.actor.display_name
},
}
};

@ -1,4 +1,5 @@
import { API_ORIGIN, API_PATH } from '../api/_entrypoint';
import { LOGIN_USER, LOAD_USER, CHANGE_ACTOR } from '../store/mutation-types';
// URL and endpoint constants
const LOGIN_URL = `${API_ORIGIN}${API_PATH}/login`;
@ -53,7 +54,7 @@ export default {
.then((response) => {
console.log('We have a new token');
this.authenticated = true;
store.commit('LOGIN_USER', response);
store.commit(LOGIN_USER, response);
localStorage.setItem('token', response.token);
console.log("Let's try to auth again");
successHandler();
@ -104,9 +105,10 @@ export default {
}).then((response) => {
this.authenticated = true;
console.log(response);
store.commit('LOAD_USER', response.data);
store.commit(LOAD_USER, response.data);
store.commit(CHANGE_ACTOR, response.data.actors[0]);
return successHandler();
});
});
},
// The object to be passed as a header for authenticated requests

@ -10,7 +10,7 @@
<v-icon>chevron_left</v-icon>
</v-btn>
<v-spacer></v-spacer>
<v-btn icon class="mr-3" v-if="$store.state.user && $store.state.user.actor.id === actor.id">
<v-btn icon class="mr-3" v-if="$store.state.user && $store.state.actor.id === actor.id">
<v-icon>edit</v-icon>
</v-btn>
<v-menu bottom left>
@ -18,10 +18,10 @@
<v-icon>more_vert</v-icon>
</v-btn>
<v-list>
<v-list-tile @click="logoutUser()" v-if="$store.state.user && $store.state.user.actor.id === actor.id">
<v-list-tile @click="logoutUser()" v-if="$store.state.user && $store.state.actor.id === actor.id">
<v-list-tile-title>User logout</v-list-tile-title>
</v-list-tile>
<v-list-tile @click="deleteAccount()" v-if="$store.state.user && $store.state.user.actor.id === actor.id">
<v-list-tile @click="deleteAccount()" v-if="$store.state.user && $store.state.actor.id === actor.id">
<v-list-tile-title>Delete</v-list-tile-title>
</v-list-tile>
</v-list>
@ -30,13 +30,13 @@
<v-spacer></v-spacer>
<div class="text-xs-center">
<v-avatar size="125px">
<img v-if="!actor.avatar_url"
<img v-if="!actor.avatar"
class="img-circle elevation-7 mb-1"
src="https://picsum.photos/125/125/"
>
<img v-else
class="img-circle elevation-7 mb-1"
:src="actor.avatar_url"
:src="actor.avatar"
>
</v-avatar>
</div>

@ -60,6 +60,7 @@
<script>
import { LOGIN_USER } from '@/store/mutation-types';
import auth from '@/auth/index';
import Gravatar from 'vue-gravatar';
import RegisterAvatar from './RegisterAvatar';
@ -119,7 +120,7 @@
loginAction(e) {
e.preventDefault();
auth.login(JSON.stringify(this.credentials), (data) => {
this.$store.commit('LOGIN_USER', data.user);
this.$store.commit(LOGIN_USER, data.user);
this.$router.push({ name: 'Home' });
}, (error) => {
Promise.resolve(error).then((errorMsg) => {

@ -1,17 +1,18 @@
<template>
<b-container>
<v-container>
<h1 v-if="loading">{{ $t('registration.validation.process') }}</h1>
<div v-else>
<div v-if="failed">
<b-alert show variant="danger">{{ $t('registration.success.validation_failure') }}</b-alert>
<v-alert :value="true" variant="danger">Error while validating account</v-alert>
</div>
<h1 v-else>{{ $t('registration.validation.finished') }}</h1>
</div>
</b-container>
</v-container>
</template>
<script>
import fetchStory from '@/api/eventFetch';
import { LOGIN_USER } from '@/store/mutation-types';
export default {
name: 'Validate',
@ -36,7 +37,7 @@ export default {
this.loading = false;
localStorage.setItem('token', data.token);
localStorage.setItem('refresh_token', data.refresh_token);
this.$store.commit('LOGIN_USER', data.account);
this.$store.commit(LOGIN_USER, data.account);
this.$snotify.success(this.$t('registration.success.login', { username: data.account.username }));
this.$router.push({ name: 'Home' });
}).catch((err) => {

@ -120,8 +120,8 @@
// });
// });
this.event.category_id = this.event.category;
this.event.organizer_actor_id = this.$store.state.user.actor.id;
this.event.participants = [this.$store.state.user.actor.id];
this.event.organizer_actor_id = this.$store.state.actor.id;
this.event.participants = [this.$store.state.actor.id];
// this.event.price = parseFloat(this.event.price);
if (this.id === undefined) {

@ -16,7 +16,7 @@
<v-icon>chevron_left</v-icon>
</v-btn>
<v-spacer></v-spacer>
<v-btn icon class="mr-3 white--text" v-if="event.organizer.id === $store.state.user.actor.id" :to="{ name: 'EditEvent', params: {id: event.id}}">
<v-btn icon class="mr-3 white--text" v-if="actorIsOrganizer()" :to="{ name: 'EditEvent', params: {id: event.id}}">
<v-icon>edit</v-icon>
</v-btn>
<v-menu bottom left>
@ -27,7 +27,7 @@
<v-list-tile @click="downloadIcsEvent()">
<v-list-tile-title>Download</v-list-tile-title>
</v-list-tile>
<v-list-tile @click="deleteEvent()" v-if="$store.state.user.actor.id === event.organizer.id">
<v-list-tile @click="deleteEvent()" v-if="actorIsOrganizer()">
<v-list-tile-title>Delete</v-list-tile-title>
</v-list-tile>
</v-list>
@ -217,10 +217,10 @@
})
},
actorIsParticipant() {
return this.event.participants.map(participant => participant.id).includes(this.$store.state.user.actor.id) || this.actorIsOrganizer();
return this.$store.state.actor && this.event.participants.map(participant => participant.id).includes(this.$store.state.actor.id) || this.actorIsOrganizer();
},
actorIsOrganizer() {
return this.$store.state.user.actor.id === this.event.organizer.id;
return this.$store.state.actor && this.$store.state.actor.id === this.event.organizer.id;
}
},
props: {

@ -11,7 +11,7 @@
<v-icon>chevron_left</v-icon>
</v-btn>
<v-spacer></v-spacer>
<!--<v-btn icon class="mr-3" v-if="$store.state.user && $store.state.user.actor.id === actor.id">-->
<!--<v-btn icon class="mr-3" v-if="$store.state.user && $store.state.actor.id === actor.id">-->
<!--<v-icon>edit</v-icon>-->
<!--</v-btn>-->
<v-btn icon>

@ -16,11 +16,11 @@
</v-layout>
</v-container>
</v-jumbotron>
<v-layout>
<v-layout v-else>
<v-flex xs12 sm8 offset-sm2>
<v-layout row wrap>
<v-flex xs12 sm6>
<h1>Welcome back {{ $store.state.user.actor.username }}</h1>
<h1>Welcome back {{ $store.state.actor.username }}</h1>
</v-flex>
<v-flex xs12 sm6>
<v-layout align-center>
@ -51,7 +51,7 @@
</v-card-media>
<v-card-title primary-title>
<div>
<span class="grey--text">{{ event.begins_on | formatDate }}</span><br>
<span class="grey--text">{{ event.begins_on | formatDay }}</span><br>
<router-link :to="{name: 'Account', params: { name: event.organizer.username } }">
<v-avatar size="25px">
<img class="img-circle elevation-7 mb-1"
@ -100,8 +100,8 @@ export default {
this.fetchData();
},
computed: {
displayed_name: function() {
return this.$store.state.user.actor.display_name === null ? this.$store.state.user.actor.username : this.$store.state.user.actor.display_name
displayed_name() {
return this.$store.state.actor.display_name === null ? this.$store.state.actor.username : this.$store.state.actor.display_name
},
},
methods: {

@ -75,8 +75,7 @@
</v-card-actions>
</v-card>
</v-menu>
<v-btn flat @click="$router.push({name: 'Account', params: { name: getUser().actor.username }})" v-if="$store.state.user">{{ this.displayed_name }}</v-btn>
<v-btn v-else :to="{ name: 'Login' }">Se connecter</v-btn>
<v-btn v-if="!$store.state.user" :to="{ name: 'Login' }">Se connecter</v-btn>
</v-toolbar>
</template>
@ -123,7 +122,10 @@
},
computed: {
displayed_name: function() {
return this.$store.state.user.actor.display_name === null ? this.$store.state.user.actor.username : this.$store.state.user.actor.display_name
console.log('displayed name', this.$store.state.actor);
if (this.$store.state.actor) {
return this.$store.state.actor.display_name === null ? this.$store.state.actor.username : this.$store.state.actor.display_name;
}
},
},
methods: {

@ -3,36 +3,21 @@
import Vue from 'vue';
// import * as VueGoogleMaps from 'vue2-google-maps';
import VueMarkdown from 'vue-markdown';
import VuetifyGoogleAutocomplete from 'vuetify-google-autocomplete';
import Vuetify from 'vuetify';
import Vuex from 'vuex';
import moment from 'moment';
import VuexI18n from 'vuex-i18n';
import 'material-design-icons/iconfont/material-icons.css';
import 'vuetify/dist/vuetify.min.css';
import App from '@/App';
import router from '@/router';
import storeData from '@/store/index';
import translations from '@/i18n/index';
import auth from '@/auth';
import App from './App.vue';
import router from './router';
import store from './store';
import translations from './i18n';
import auth from './auth';
Vue.config.productionTip = false;
Vue.use(VuetifyGoogleAutocomplete, {
apiKey: 'AIzaSyBF37pw38j0giICt73TCAPNogc07Upe_Q4', // Can also be an object. E.g, for Google Maps Premium API, pass `{ client: <YOUR-CLIENT-ID> }`
});
/*Vue.use(VueGoogleMaps, {
load: {
key: 'AIzaSyBF37pw38j0giICt73TCAPNogc07Upe_Q4',
libraries: 'places',
installComponents: false,
},
});*/
Vue.use(VueMarkdown);
Vue.use(Vuetify);
Vue.use(Vuex);
let language = window.navigator.userLanguage || window.navigator.language;
moment.locale(language);
@ -43,8 +28,6 @@ if (!(language in translations)) {
[language] = language.split('-', 1);
}
const store = new Vuex.Store(storeData);
Vue.use(VuexI18n.plugin, store);
Object.entries(translations).forEach((key) => {
@ -55,17 +38,21 @@ Vue.i18n.set(language);
Vue.i18n.fallback('en');
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiredAuth) && store.state.user === undefined || store.state.user == null) {
if (to.matched.some(record => record.meta.requiredAuth)) {
next({
name: 'Login',
query: { redirect: to.fullPath }
query: { redirect: to.fullPath },
});
} else {
next();
}
});
auth.getUser(store, () => {}, () => {});
auth.getUser(store, () => {}, (error) => {
console.warn(error);
});
console.log('store', store);
/* eslint-disable no-new */
new Vue({

@ -1,8 +1,12 @@
import { LOGIN_USER, LOGOUT_USER, LOAD_USER } from './mutation-types';
import Vue from 'vue';
import Vuex from 'vuex';
import { LOGIN_USER, LOGOUT_USER, LOAD_USER, CHANGE_ACTOR } from './mutation-types';
const state = {
isLogged: !!localStorage.getItem('token'),
user: false,
actor: false,
defaultActor: localStorage.getItem('defaultActor') || null,
};
/* eslint-disable */
@ -20,7 +24,21 @@ const mutations = {
state.isLogged = false;
state.user = null;
},
[CHANGE_ACTOR](state, actor) {
state.actor = actor;
state.defaultActor = actor.username;
}
};
/* eslint-enable */
export default { state, mutations };
Vue.use(Vuex);
const store = new Vuex.Store({ state, mutations });
store.subscribe((mutation, localState) => {
if (mutation === CHANGE_ACTOR) {
localStorage.setItem('defaultActor', localState.actor.username);
}
});
export default store;

@ -1,3 +1,4 @@
export const LOGIN_USER = 'LOGIN_USER';
export const LOAD_USER = 'LOAD_USER';
export const LOGOUT_USER = 'LOGOUT_USER';
export const CHANGE_ACTOR = 'CHANGE_ACTOR';

@ -68,7 +68,7 @@ defmodule Eventos.Actors.Actor do
many_to_many :followers, Actor, join_through: Follower
has_many :organized_events, Event, [foreign_key: :organizer_actor_id]
many_to_many :memberships, Actor, join_through: Member
has_one :user, User
belongs_to :user, User
timestamps()
end
@ -83,7 +83,7 @@ defmodule Eventos.Actors.Actor do
def registration_changeset(%Actor{} = actor, attrs) do
actor
|> Ecto.Changeset.cast(attrs, [:preferred_username, :domain, :name, :summary, :keys, :keys, :suspended, :url, :type, :avatar_url])
|> Ecto.Changeset.cast(attrs, [:preferred_username, :domain, :name, :summary, :keys, :keys, :suspended, :url, :type, :avatar_url, :user_id])
|> unique_constraint(:preferred_username, name: :actors_preferred_username_domain_index)
|> put_change(:url, "#{EventosWeb.Endpoint.url()}/@#{attrs["prefered_username"]}")
|> validate_required([:preferred_username, :keys, :suspended, :url, :type])

@ -177,7 +177,7 @@ defmodule Eventos.Actors do
def list_users_with_actors do
users = Repo.all(User)
Repo.preload(users, :actor)
Repo.preload(users, :actors)
end
defp blank?(""), do: nil
@ -222,7 +222,7 @@ defmodule Eventos.Actors do
def get_user_with_actor!(id) do
user = Repo.get!(User, id)
Repo.preload(user, :actor)
Repo.preload(user, :actors)
end
def get_actor_by_url(url) do
@ -312,7 +312,7 @@ defmodule Eventos.Actors do
Get an user by email
"""
def find_by_email(email) do
case Repo.preload(Repo.get_by(User, email: email), :actor) do
case Repo.preload(Repo.get_by(User, email: email), :actors) do
nil ->
{:error, nil}
user ->

@ -8,8 +8,9 @@ defmodule Eventos.Actors.Service.Activation do
@doc false
def check_confirmation_token(token) when is_binary(token) do
with %User{} = user <- Repo.get_by(User, confirmation_token: token) do
Actors.update_user(user, %{"confirmed_at" => DateTime.utc_now(), "confirmation_sent_at" => nil, "confirmation_token" => nil})
with %User{} = user <- Repo.get_by(User, confirmation_token: token),
{:ok, %User{} = user} <- Actors.update_user(user, %{"confirmed_at" => DateTime.utc_now(), "confirmation_sent_at" => nil, "confirmation_token" => nil}) do
{:ok, Repo.preload(user, :actors)}
else
_err ->
{:error, "Invalid token"}

@ -11,7 +11,7 @@ defmodule Eventos.Actors.User do
field :password_hash, :string
field :password, :string, virtual: true
field :role, :integer, default: 0
belongs_to :actor, Actor
has_many :actors, Actor
field :confirmed_at, :utc_datetime
field :confirmation_sent_at, :utc_datetime
field :confirmation_token, :string
@ -24,7 +24,7 @@ defmodule Eventos.Actors.User do
@doc false
def changeset(%User{} = user, attrs) do
user
|> cast(attrs, [:email, :role, :password_hash, :actor_id, :confirmed_at, :confirmation_sent_at, :confirmation_token, :reset_password_sent_at, :reset_password_token])
|> cast(attrs, [:email, :role, :password_hash, :confirmed_at, :confirmation_sent_at, :confirmation_token, :reset_password_sent_at, :reset_password_token])
|> validate_required([:email])
|> unique_constraint(:email, [message: "registration.error.email_already_used"])
|> validate_format(:email, ~r/@/)

@ -20,7 +20,7 @@ defmodule EventosWeb.GroupController do
conn
|> put_status(:created)
|> put_resp_header("location", actor_path(conn, :show, group))
|> render(EventosWeb.ActorView, "acccount_basic.json", actor: group)
|> render(EventosWeb.ActorView, "actor_basic.json", actor: group)
end
end

@ -92,7 +92,7 @@ defmodule EventosWeb.UserController do
def show_current_actor(conn, _params) do
user = conn
|> Guardian.Plug.current_resource()
|> Repo.preload(:actor)
|> Repo.preload(:actors)
render(conn, "show_simple.json", user: user)
end

@ -7,7 +7,7 @@ defmodule EventosWeb.ActorView do
alias Eventos.Actors
def render("index.json", %{actors: actors}) do
%{data: render_many(actors, ActorView, "acccount_basic.json")}
%{data: render_many(actors, ActorView, "actor_basic.json")}
end
def render("show.json", %{actor: actor}) do
@ -18,7 +18,7 @@ defmodule EventosWeb.ActorView do
%{data: render_one(actor, ActorView, "actor_basic.json")}
end
def render("acccount_basic.json", %{actor: actor}) do
def render("actor_basic.json", %{actor: actor}) do
%{id: actor.id,
username: actor.preferred_username,
domain: actor.domain,

@ -53,8 +53,8 @@ defmodule EventosWeb.EventView do
begins_on: event.begins_on,
ends_on: event.ends_on,
uuid: event.uuid,
organizer: render_one(event.organizer_actor, ActorView, "acccount_basic.json"),
participants: render_many(event.participants, ActorView, "acccount_basic.json"),
organizer: render_one(event.organizer_actor, ActorView, "actor_basic.json"),
participants: render_many(event.participants, ActorView, "actor_basic.json"),
physical_address: render_one(event.physical_address, AddressView, "address.json"),
type: "Event",
address_type: event.address_type,

@ -32,7 +32,7 @@ defmodule EventosWeb.GroupView do
description: group.description,
suspended: group.suspended,
url: group.url,
members: render_many(group.members, ActorView, "acccount_basic.json"),
members: render_many(group.members, ActorView, "actor_basic.json"),
events: render_many(group.organized_events, EventView, "event_simple.json")
}
end

@ -16,8 +16,8 @@ defmodule EventosWeb.MemberView do
def render("member.json", %{member: member}) do
%{
role: member.role,
actor: render_one(member.actor, ActorView, "acccount_basic.json"),
group: render_one(member.parent, ActorView, "acccount_basic.json")
actor: render_one(member.actor, ActorView, "actor_basic.json"),
group: render_one(member.parent, ActorView, "actor_basic.json")
}
end
end

@ -9,7 +9,7 @@ defmodule EventosWeb.SearchView do
%{
data: %{
events: render_many(events, EventView, "event_simple.json"),
actors: render_many(actors, ActorView, "acccount_basic.json"),
actors: render_many(actors, ActorView, "actor_basic.json"),
}
}
end

@ -28,14 +28,14 @@ defmodule EventosWeb.UserView do
def render("user_simple.json", %{user: user}) do
%{id: user.id,
role: user.role,
actor: render_one(user.actor, ActorView, "acccount_basic.json")
actors: render_many(user.actors, ActorView, "actor_basic.json")
}
end
def render("user.json", %{user: user}) do
%{id: user.id,
role: user.role,
actor: render_one(user.actor, ActorView, "actor.json")
actors: render_many(user.actors, ActorView, "actor.json")
}
end

@ -0,0 +1,23 @@
defmodule Eventos.Repo.Migrations.AllowMultipleAccountsForUser do
use Ecto.Migration
def up do
alter table(:actors) do
add :user_id, references(:users, on_delete: :delete_all), null: true
end
alter table(:users) do
remove :actor_id
end
end
def down do
alter table(:users) do
add :actor_id, references(:actors, on_delete: :delete_all), null: false
end
alter table(:actors) do
remove :user_id
end
end
end

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,2 +0,0 @@
!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,a){for(var u,i,f,s=0,l=[];s<t.length;s++)i=t[s],o[i]&&l.push(o[i][0]),o[i]=0;for(u in c)Object.prototype.hasOwnProperty.call(c,u)&&(e[u]=c[u]);for(r&&r(t,c,a);l.length;)l.shift()();if(a)for(s=0;s<a.length;s++)f=n(n.s=a[s]);return f};var t={},o={2:0};n.e=function(e){function r(){u.onerror=u.onload=null,clearTimeout(i);var n=o[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var a=document.getElementsByTagName("head")[0],u=document.createElement("script");u.type="text/javascript",u.charset="utf-8",u.async=!0,u.timeout=12e4,n.nc&&u.setAttribute("nonce",n.nc),u.src=n.p+"js/"+e+"."+{0:"0d63a19c6680451dd336",1:"29c4f33994925affb616"}[e]+".js";var i=setTimeout(r,12e4);return u.onerror=u.onload=r,a.appendChild(u),c},n.m=e,n.c=t,n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="/",n.oe=function(e){throw console.error(e),e}}([]);
//# sourceMappingURL=manifest.881ff1dba0c9e5d0130f.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -6,15 +6,15 @@ defmodule EventosWeb.ActorControllerTest do
alias Eventos.Actors
setup %{conn: conn} do
actor = insert(:actor)
user = insert(:user, actor: actor)
{:ok, conn: conn, user: user}
user = insert(:user)
actor = insert(:actor, user: user)
{:ok, conn: conn, user: user, actor: actor}
end
describe "index" do
test "lists all actors", %{conn: conn, user: user} do
test "lists all actors", %{conn: conn, user: user, actor: actor} do
conn = get conn, actor_path(conn, :index)
assert hd(json_response(conn, 200)["data"])["username"] == user.actor.preferred_username
assert hd(json_response(conn, 200)["data"])["username"] == actor.preferred_username
end
end
@ -41,9 +41,4 @@ defmodule EventosWeb.ActorControllerTest do
# assert response(conn, 200)
# end
# end
defp create_actor(_) do
actor = insert(:actor)
{:ok, actor: actor}
end
end

@ -16,8 +16,8 @@ defmodule EventosWeb.AddressControllerTest do
end
setup %{conn: conn} do
actor = insert(:actor)
user = insert(:user, actor: actor)
user = insert(:user)
actor = insert(:actor, user: user)
{:ok, conn: conn, user: user}
end

@ -11,8 +11,8 @@ defmodule EventosWeb.BotControllerTest do
@invalid_attrs %{source: nil, type: nil, name: nil}
setup %{conn: conn} do
actor = insert(:actor)
user = insert(:user, actor: actor)
user = insert(:user)
actor = insert(:actor, user: user)
{:ok, conn: put_req_header(conn, "accept", "application/json"), user: user}
end

@ -16,8 +16,8 @@ defmodule EventosWeb.CategoryControllerTest do
end
setup %{conn: conn} do
actor = insert(:actor)
user = insert(:user, actor: actor)
user = insert(:user)
actor = insert(:actor, user: user)
{:ok, conn: conn, user: user}
end

@ -11,15 +11,14 @@ defmodule EventosWeb.CommentControllerTest do
@invalid_attrs %{text: nil, url: nil}
setup %{conn: conn} do
actor = insert(:actor)
user = insert(:user, actor: actor)
{:ok, conn: put_req_header(conn, "accept", "application/json"), user: user}
user = insert(:user)
actor = insert(:actor, user: user)
{:ok, conn: put_req_header(conn, "accept", "application/json"), user: user, actor: actor}
end
describe "create comment" do
test "renders comment when data is valid", %{conn: conn, user: user} do
test "renders comment when data is valid", %{conn: conn, user: user, actor: actor} do
conn = auth_conn(conn, user)
actor = insert(:actor)
attrs = Map.merge(@create_attrs, %{actor_id: actor.id})
conn = post conn, comment_path(conn, :create), comment: attrs
assert %{"uuid" => uuid, "id" => id} = json_response(conn, 201)["data"]
@ -43,9 +42,8 @@ defmodule EventosWeb.CommentControllerTest do
describe "update comment" do
setup [:create_comment]
test "renders comment when data is valid", %{conn: conn, comment: %Comment{id: id, uuid: uuid} = comment, user: user} do
test "renders comment when data is valid", %{conn: conn, comment: %Comment{id: id, uuid: uuid} = comment, user: user, actor: actor} do
conn = auth_conn(conn, user)
actor = insert(:actor)
attrs = Map.merge(@update_attrs, %{actor_id: actor.id})
conn = put conn, comment_path(conn, :update, uuid), comment: attrs
assert %{"uuid" => uuid, "id" => id} = json_response(conn, 200)["data"]

@ -21,9 +21,9 @@ defmodule EventosWeb.EventControllerTest do
end
setup %{conn: conn} do
actor = insert(:actor)
user = insert(:user, actor: actor)
{:ok, conn: conn, user: user}
user = insert(:user)
actor = insert(:actor, user: user)
{:ok, conn: conn, user: user, actor: actor}
end
describe "index" do
@ -34,8 +34,8 @@ defmodule EventosWeb.EventControllerTest do
end
describe "create event" do
test "renders event when data is valid", %{conn: conn, user: user} do
attrs = Map.put(@create_attrs, :organizer_actor_id, user.actor.id)
test "renders event when data is valid", %{conn: conn, user: user, actor: actor} do
attrs = Map.put(@create_attrs, :organizer_actor_id, actor.id)
attrs = Map.put(attrs, "physical_address", @create_address_attrs)
category = insert(:category)
@ -55,9 +55,9 @@ defmodule EventosWeb.EventControllerTest do
} = json_response(conn, 200)["data"]
end
test "renders errors when data is invalid", %{conn: conn, user: user} do
test "renders errors when data is invalid", %{conn: conn, user: user, actor: actor} do
conn = auth_conn(conn, user)
attrs = Map.put(@invalid_attrs, :organizer_actor_id, user.actor.id)
attrs = Map.put(@invalid_attrs, :organizer_actor_id, actor.id)
attrs = Map.put(attrs, :address, @create_address_attrs)
conn = post conn, event_path(conn, :create), event: attrs
assert json_response(conn, 422)["errors"] != %{}
@ -78,10 +78,10 @@ defmodule EventosWeb.EventControllerTest do
describe "update event" do
setup [:create_event]
test "renders event when data is valid", %{conn: conn, event: %Event{uuid: uuid} = event, user: user} do
test "renders event when data is valid", %{conn: conn, event: %Event{uuid: uuid} = event, user: user, actor: actor} do
conn = auth_conn(conn, user)
address = address_fixture()
attrs = Map.put(@update_attrs, :organizer_actor_id, user.actor.id)
attrs = Map.put(@update_attrs, :organizer_actor_id, actor.id)
attrs = Map.put(attrs, :address_id, address.id)
conn = put conn, event_path(conn, :update, uuid), event: attrs
assert %{"uuid" => uuid} = json_response(conn, 200)["data"]
@ -97,9 +97,9 @@ defmodule EventosWeb.EventControllerTest do
} = json_response(conn, 200)["data"]
end
test "renders errors when data is invalid", %{conn: conn, event: %Event{uuid: uuid} = event, user: user} do
test "renders errors when data is invalid", %{conn: conn, event: %Event{uuid: uuid} = event, user: user, actor: actor} do
conn = auth_conn(conn, user)
attrs = Map.put(@invalid_attrs, :organizer_actor_id, user.actor.id)
attrs = Map.put(@invalid_attrs, :organizer_actor_id, actor.id)
conn = put conn, event_path(conn, :update, uuid), event: attrs
assert json_response(conn, 422)["errors"] != %{}
end

@ -16,8 +16,8 @@ defmodule EventosWeb.SessionControllerTest do
end
setup %{conn: conn} do
actor = insert(:actor)
user = insert(:user, actor: actor)
user = insert(:user)
actor = insert(:actor, user: user)
event = insert(:event, organizer_actor: actor)
{:ok, conn: conn, user: user, event: event}
end

@ -16,8 +16,8 @@ defmodule EventosWeb.TagControllerTest do
end
setup %{conn: conn} do
actor = insert(:actor)
user = insert(:user, actor: actor)
user = insert(:user)
actor = insert(:actor, user: user)
{:ok, conn: conn, user: user}
end

@ -16,8 +16,8 @@ defmodule EventosWeb.TrackControllerTest do
end
setup %{conn: conn} do
actor = insert(:actor)
user = insert(:user, actor: actor)
user = insert(:user)
actor = insert(:actor, user: user)
event = insert(:event, organizer_actor: actor)
{:ok, conn: conn, user: user, event: event}
end

@ -16,8 +16,8 @@ defmodule EventosWeb.UserControllerTest do
end
setup %{conn: conn} do
actor = insert(:actor)
user = insert(:user, actor: actor)
user = insert(:user)
actor = insert(:actor, user: user)
{:ok, conn: conn, user: user}
end

@ -10,7 +10,6 @@ defmodule Eventos.Factory do
password_hash: "Jane Smith",
email: sequence(:email, &"email-#{&1}@example.com"),
role: 0,
actor: build(:actor)
}
end
@ -25,7 +24,8 @@ defmodule Eventos.Factory do
preferred_username: preferred_username,
domain: nil,
keys: pem,
url: EventosWeb.Endpoint.url() <> "/@#{preferred_username}"
url: EventosWeb.Endpoint.url() <> "/@#{preferred_username}",
user: nil,
}
end

Loading…
Cancel
Save