Allow multiple identities (accounts actors) for one user.
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
a71b81af91
commit
dee437e4f3
@ -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…
Reference in New Issue
Block a user