Merge branch 'upgrade-deps' into 'master'
Fixes Closes #674 See merge request framasoft/mobilizon!893
This commit is contained in:
commit
d269b52201
@ -28,7 +28,6 @@
|
||||
"bulma-divider": "^0.2.0",
|
||||
"core-js": "^3.6.4",
|
||||
"date-fns": "^2.16.0",
|
||||
"eslint-plugin-cypress": "^2.10.3",
|
||||
"graphql": "^15.0.0",
|
||||
"graphql-tag": "^2.10.3",
|
||||
"intersection-observer": "^0.12.0",
|
||||
@ -42,7 +41,7 @@
|
||||
"tiptap": "^1.32.0",
|
||||
"tiptap-extensions": "^1.34.0",
|
||||
"unfetch": "^4.2.0",
|
||||
"v-tooltip": "^2.1.2",
|
||||
"v-tooltip": "^2.1.3",
|
||||
"vue": "^2.6.11",
|
||||
"vue-apollo": "^3.0.3",
|
||||
"vue-class-component": "^7.2.3",
|
||||
@ -78,17 +77,20 @@
|
||||
"@vue/eslint-config-prettier": "^6.0.0",
|
||||
"@vue/eslint-config-typescript": "^7.0.0",
|
||||
"@vue/test-utils": "^1.1.0",
|
||||
"eslint": "^7.7.0",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-config-prettier": "^7.0.0",
|
||||
"eslint-plugin-cypress": "^2.10.3",
|
||||
"eslint-plugin-import": "^2.20.2",
|
||||
"eslint-plugin-prettier": "^3.1.3",
|
||||
"eslint-plugin-vue": "^7.0.0",
|
||||
"eslint-plugin-vue": "^7.9.0",
|
||||
"flush-promises": "^1.0.2",
|
||||
"jest-junit": "^12.0.0",
|
||||
"mock-apollo-client": "^0.6",
|
||||
"prettier": "2.2.1",
|
||||
"prettier-eslint": "^12.0.0",
|
||||
"sass": "^1.29.0",
|
||||
"sass-loader": "^10.0.1",
|
||||
"typescript": "^4.2.3",
|
||||
"sass-loader": "^8.0.2",
|
||||
"typescript": "~4.1.5",
|
||||
"vue-cli-plugin-svg": "~0.1.3",
|
||||
"vue-i18n-extract": "^1.0.2",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
|
@ -158,10 +158,14 @@ const router = new Router({
|
||||
|
||||
router.beforeEach(authGuardIfNeeded);
|
||||
router.afterEach(() => {
|
||||
if (router.app.$children[0]) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
router.app.$children[0].error = null;
|
||||
try {
|
||||
if (router.app.$children[0]) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
router.app.$children[0].error = null;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -67,7 +67,7 @@
|
||||
</b-field>
|
||||
|
||||
<p class="control has-text-centered" v-if="!submitted">
|
||||
<button class="button is-primary is-large">
|
||||
<button type="submit" class="button is-primary is-large">
|
||||
{{ $t("Login") }}
|
||||
</button>
|
||||
</p>
|
||||
@ -222,44 +222,51 @@ export default class Login extends Vue {
|
||||
}
|
||||
|
||||
saveUserData(data.login);
|
||||
|
||||
await this.$apollo.mutate({
|
||||
mutation: UPDATE_CURRENT_USER_CLIENT,
|
||||
variables: {
|
||||
id: data.login.user.id,
|
||||
email: this.credentials.email,
|
||||
isLoggedIn: true,
|
||||
role: data.login.user.role,
|
||||
},
|
||||
});
|
||||
try {
|
||||
await initializeCurrentActor(this.$apollo.provider.defaultClient);
|
||||
} catch (err) {
|
||||
if (err instanceof NoIdentitiesException) {
|
||||
this.$router.push({
|
||||
name: RouteName.REGISTER_PROFILE,
|
||||
params: {
|
||||
email: this.currentUser.email,
|
||||
userAlreadyActivated: "true",
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
await this.setupClientUserAndActors(data.login);
|
||||
|
||||
if (this.$route.query.redirect) {
|
||||
console.log("redirect", this.$route.query.redirect);
|
||||
this.$router.push(this.$route.query.redirect as string);
|
||||
return;
|
||||
}
|
||||
window.localStorage.setItem("welcome-back", "yes");
|
||||
if (window.localStorage) {
|
||||
window.localStorage.setItem("welcome-back", "yes");
|
||||
}
|
||||
this.$router.push({ name: RouteName.HOME });
|
||||
return;
|
||||
} catch (err) {
|
||||
this.submitted = false;
|
||||
console.error(err);
|
||||
err.graphQLErrors.forEach(({ message }: { message: string }) => {
|
||||
this.errors.push(message);
|
||||
});
|
||||
if (err.graphQLErrors) {
|
||||
err.graphQLErrors.forEach(({ message }: { message: string }) => {
|
||||
this.errors.push(message);
|
||||
});
|
||||
} else if (err.networkError) {
|
||||
this.errors.push(err.networkError.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async setupClientUserAndActors(login: ILogin): Promise<void> {
|
||||
await this.$apollo.mutate({
|
||||
mutation: UPDATE_CURRENT_USER_CLIENT,
|
||||
variables: {
|
||||
id: login.user.id,
|
||||
email: this.credentials.email,
|
||||
isLoggedIn: true,
|
||||
role: login.user.role,
|
||||
},
|
||||
});
|
||||
try {
|
||||
await initializeCurrentActor(this.$apollo.provider.defaultClient);
|
||||
} catch (err) {
|
||||
if (err instanceof NoIdentitiesException) {
|
||||
this.$router.push({
|
||||
name: RouteName.REGISTER_PROFILE,
|
||||
params: {
|
||||
email: this.currentUser.email,
|
||||
userAlreadyActivated: "true",
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,23 +2,45 @@ import { config, createLocalVue, mount } from "@vue/test-utils";
|
||||
import { routes } from "@/router";
|
||||
import App from "@/App.vue";
|
||||
import VueRouter from "vue-router";
|
||||
import Home from "@/views/Home.vue";
|
||||
import Buefy from "buefy";
|
||||
|
||||
const localVue = createLocalVue();
|
||||
config.mocks.$t = (key: string): string => key;
|
||||
localVue.use(VueRouter);
|
||||
|
||||
const router = new VueRouter({ routes });
|
||||
const wrapper = mount(App, {
|
||||
localVue,
|
||||
router,
|
||||
stubs: ["NavBar", "mobilizon-footer"],
|
||||
});
|
||||
localVue.use(Buefy);
|
||||
|
||||
describe("routing", () => {
|
||||
test("Homepage", async () => {
|
||||
router.push("/");
|
||||
const router = new VueRouter({ routes, mode: "history" });
|
||||
const wrapper = mount(App, {
|
||||
localVue,
|
||||
router,
|
||||
stubs: {
|
||||
NavBar: true,
|
||||
"mobilizon-footer": true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper.html()).toContain('<div id="homepage">');
|
||||
});
|
||||
|
||||
test("About", async () => {
|
||||
const router = new VueRouter({ routes, mode: "history" });
|
||||
const wrapper = mount(App, {
|
||||
localVue,
|
||||
router,
|
||||
stubs: {
|
||||
NavBar: true,
|
||||
"mobilizon-footer": true,
|
||||
},
|
||||
});
|
||||
|
||||
router.push("/about");
|
||||
await wrapper.vm.$nextTick();
|
||||
expect(wrapper.findComponent(Home).exists()).toBe(true);
|
||||
await wrapper.vm.$nextTick();
|
||||
expect(wrapper.vm.$route.path).toBe("/about/instance");
|
||||
expect(wrapper.html()).toContain(
|
||||
'<a href="/about/instance" aria-current="page"'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
183
js/tests/unit/specs/components/User/login.spec.ts
Normal file
183
js/tests/unit/specs/components/User/login.spec.ts
Normal file
@ -0,0 +1,183 @@
|
||||
import { config, createLocalVue, mount, Wrapper } from "@vue/test-utils";
|
||||
import Login from "@/views/User/Login.vue";
|
||||
import Buefy from "buefy";
|
||||
import {
|
||||
createMockClient,
|
||||
MockApolloClient,
|
||||
RequestHandler,
|
||||
} from "mock-apollo-client";
|
||||
import VueApollo from "vue-apollo";
|
||||
import buildCurrentUserResolver from "@/apollo/user";
|
||||
import { InMemoryCache } from "apollo-cache-inmemory";
|
||||
import { configMock } from "../../mocks/config";
|
||||
import { i18n } from "@/utils/i18n";
|
||||
import { CONFIG } from "@/graphql/config";
|
||||
import { loginMock, loginResponseMock } from "../../mocks/auth";
|
||||
import { LOGIN } from "@/graphql/auth";
|
||||
import { CURRENT_USER_CLIENT } from "@/graphql/user";
|
||||
import { ICurrentUser } from "@/types/current-user.model";
|
||||
import flushPromises from "flush-promises";
|
||||
import RouteName from "@/router/name";
|
||||
|
||||
const localVue = createLocalVue();
|
||||
localVue.use(Buefy);
|
||||
config.mocks.$t = (key: string): string => key;
|
||||
const $router = { push: jest.fn() };
|
||||
|
||||
describe("Render login form", () => {
|
||||
let wrapper: Wrapper<Vue>;
|
||||
let mockClient: MockApolloClient | null;
|
||||
let apolloProvider;
|
||||
let requestHandlers: Record<string, RequestHandler>;
|
||||
|
||||
const generateWrapper = (
|
||||
handlers: Record<string, unknown> = {},
|
||||
customProps: Record<string, unknown> = {},
|
||||
baseData: Record<string, unknown> = {},
|
||||
customMocks: Record<string, unknown> = {}
|
||||
) => {
|
||||
const cache = new InMemoryCache({ addTypename: true });
|
||||
|
||||
mockClient = createMockClient({
|
||||
cache,
|
||||
resolvers: buildCurrentUserResolver(cache),
|
||||
});
|
||||
|
||||
requestHandlers = {
|
||||
configQueryHandler: jest.fn().mockResolvedValue(configMock),
|
||||
loginMutationHandler: jest.fn().mockResolvedValue(loginResponseMock),
|
||||
...handlers,
|
||||
};
|
||||
mockClient.setRequestHandler(CONFIG, requestHandlers.configQueryHandler);
|
||||
mockClient.setRequestHandler(LOGIN, requestHandlers.loginMutationHandler);
|
||||
|
||||
apolloProvider = new VueApollo({
|
||||
defaultClient: mockClient,
|
||||
});
|
||||
|
||||
wrapper = mount(Login, {
|
||||
localVue,
|
||||
i18n,
|
||||
apolloProvider,
|
||||
propsData: {
|
||||
...customProps,
|
||||
},
|
||||
mocks: {
|
||||
$route: { query: {} },
|
||||
$router,
|
||||
...customMocks,
|
||||
},
|
||||
stubs: ["router-link", "router-view"],
|
||||
data() {
|
||||
return {
|
||||
...baseData,
|
||||
};
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
mockClient = null;
|
||||
apolloProvider = null;
|
||||
$router.push.mockReset();
|
||||
});
|
||||
|
||||
it("requires email and password to be filled", async () => {
|
||||
generateWrapper();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(wrapper.exists()).toBe(true);
|
||||
expect(requestHandlers.configQueryHandler).toHaveBeenCalled();
|
||||
expect(wrapper.vm.$apollo.queries.config).toBeTruthy();
|
||||
wrapper.find('form input[type="email"]').setValue("");
|
||||
wrapper.find('form input[type="password"]').setValue("");
|
||||
wrapper.find("form button.button").trigger("click");
|
||||
const form = wrapper.find("form");
|
||||
expect(form.exists()).toBe(true);
|
||||
const formElement = form.element as HTMLFormElement;
|
||||
expect(formElement.checkValidity()).toBe(false);
|
||||
});
|
||||
|
||||
it("renders and submits the login form", async () => {
|
||||
generateWrapper();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(wrapper.exists()).toBe(true);
|
||||
expect(requestHandlers.configQueryHandler).toHaveBeenCalled();
|
||||
expect(wrapper.vm.$apollo.queries.config).toBeTruthy();
|
||||
wrapper.find('form input[type="email"]').setValue("some@email.tld");
|
||||
wrapper.find('form input[type="password"]').setValue("somepassword");
|
||||
wrapper.find("form").trigger("submit");
|
||||
await wrapper.vm.$nextTick();
|
||||
expect(requestHandlers.loginMutationHandler).toHaveBeenCalledWith({
|
||||
...loginMock,
|
||||
});
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
const currentUser = mockClient?.cache.readQuery<{
|
||||
currentUser: ICurrentUser;
|
||||
}>({
|
||||
query: CURRENT_USER_CLIENT,
|
||||
})?.currentUser;
|
||||
expect(currentUser?.email).toBe("some@email.tld");
|
||||
expect(currentUser?.id).toBe("1");
|
||||
expect(jest.isMockFunction(wrapper.vm.$router.push)).toBe(true);
|
||||
await flushPromises();
|
||||
expect($router.push).toHaveBeenCalledWith({ name: RouteName.HOME });
|
||||
});
|
||||
|
||||
it("handles a login error", async () => {
|
||||
generateWrapper({
|
||||
loginMutationHandler: jest.fn().mockResolvedValue({
|
||||
errors: [
|
||||
{
|
||||
message:
|
||||
'"Impossible to authenticate, either your email or password are invalid."',
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
expect(wrapper.exists()).toBe(true);
|
||||
expect(requestHandlers.configQueryHandler).toHaveBeenCalled();
|
||||
expect(wrapper.vm.$apollo.queries.config).toBeTruthy();
|
||||
wrapper.find('form input[type="email"]').setValue("some@email.tld");
|
||||
wrapper.find('form input[type="password"]').setValue("somepassword");
|
||||
wrapper.find("form").trigger("submit");
|
||||
await wrapper.vm.$nextTick();
|
||||
expect(requestHandlers.loginMutationHandler).toHaveBeenCalledWith({
|
||||
...loginMock,
|
||||
});
|
||||
await flushPromises();
|
||||
expect(wrapper.find("article.message.is-danger").text()).toContain(
|
||||
"Impossible to authenticate, either your email or password are invalid."
|
||||
);
|
||||
expect($router.push).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("handles redirection after login", async () => {
|
||||
generateWrapper(
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
$route: { query: { redirect: "/about/instance" } },
|
||||
}
|
||||
);
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
wrapper.find('form input[type="email"]').setValue("some@email.tld");
|
||||
wrapper.find('form input[type="password"]').setValue("somepassword");
|
||||
wrapper.find("form").trigger("submit");
|
||||
await flushPromises();
|
||||
expect($router.push).toHaveBeenCalledWith("/about/instance");
|
||||
});
|
||||
});
|
20
js/tests/unit/specs/mocks/auth.ts
Normal file
20
js/tests/unit/specs/mocks/auth.ts
Normal file
@ -0,0 +1,20 @@
|
||||
export const loginMock = {
|
||||
email: "some@email.tld",
|
||||
password: "somepassword",
|
||||
};
|
||||
|
||||
export const loginResponseMock = {
|
||||
data: {
|
||||
login: {
|
||||
__typename: "Login",
|
||||
accessToken: "some access token",
|
||||
refreshToken: "some refresh token",
|
||||
user: {
|
||||
__typename: "User",
|
||||
email: "some@email.tld",
|
||||
id: "1",
|
||||
role: "ADMINISTRATOR",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
@ -38,7 +38,7 @@ module.exports = {
|
||||
css: {
|
||||
loaderOptions: {
|
||||
scss: {
|
||||
additionalData: `@import "@/variables.scss";`,
|
||||
prependData: `@import "@/variables.scss";`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
742
js/yarn.lock
742
js/yarn.lock
File diff suppressed because it is too large
Load Diff
@ -29,6 +29,9 @@ defmodule Mobilizon.Web.Plugs.HTTPSecurityPlug do
|
||||
referrer_policy = Config.get([:http_security, :referrer_policy])
|
||||
|
||||
[
|
||||
{"x-xss-protection", "0"},
|
||||
{"x-frame-options", "DENY"},
|
||||
{"x-content-type-options", "nosniff"},
|
||||
{"referrer-policy", referrer_policy},
|
||||
{"content-security-policy", csp_string()}
|
||||
]
|
||||
@ -42,44 +45,57 @@ defmodule Mobilizon.Web.Plugs.HTTPSecurityPlug do
|
||||
|
||||
@csp_start [Enum.join(@static_csp_rules, ";") <> ";"]
|
||||
|
||||
@img_src "img-src 'self' data: blob: "
|
||||
@media_src "media-src 'self' "
|
||||
# Connect-src is available for any origin (*) because of webfinger query to redirect to content
|
||||
@connect_src "connect-src 'self' * blob: "
|
||||
# unsafe-eval is because of JS issues with regenerator-runtime
|
||||
# unsafe-inline will be overriten in prod with sha256 hash
|
||||
@script_src "script-src 'self' 'unsafe-eval' 'unsafe-inline' "
|
||||
@style_src "style-src 'self' "
|
||||
@font_src "font-src 'self' "
|
||||
|
||||
defp csp_string do
|
||||
scheme = Config.get([Pleroma.Web.Endpoint, :url])[:scheme]
|
||||
static_url = Mobilizon.Web.Endpoint.static_url()
|
||||
websocket_url = Mobilizon.Web.Endpoint.websocket_url()
|
||||
|
||||
img_src =
|
||||
["img-src 'self' data: blob: "] ++ Config.get([:http_security, :csp_policy, :img_src])
|
||||
img_src = [@img_src | get_csp_config(:img_src)]
|
||||
|
||||
media_src = ["media-src 'self' "] ++ Config.get([:http_security, :csp_policy, :media_src])
|
||||
media_src = [@media_src | get_csp_config(:media_src)]
|
||||
|
||||
# Connect-src is available for any origin because of webfinger query to redirect to content
|
||||
connect_src =
|
||||
["connect-src 'self' * blob: ", static_url, ?\s, websocket_url] ++
|
||||
Config.get([:http_security, :csp_policy, :connect_src])
|
||||
connect_src = [
|
||||
@connect_src,
|
||||
static_url,
|
||||
?\s,
|
||||
websocket_url,
|
||||
?\s,
|
||||
get_csp_config(:connect_src)
|
||||
]
|
||||
|
||||
script_src =
|
||||
if Config.get(:env) == :dev do
|
||||
"script-src 'self' 'unsafe-eval' 'unsafe-inline' "
|
||||
@script_src
|
||||
else
|
||||
"script-src 'self' 'unsafe-eval' 'sha256-4RS22DYeB7U14dra4KcQYxmwt5HkOInieXK1NUMBmQI=' "
|
||||
[
|
||||
@script_src,
|
||||
"'sha256-4RS22DYeB7U14dra4KcQYxmwt5HkOInieXK1NUMBmQI=' "
|
||||
]
|
||||
end
|
||||
|
||||
script_src = [script_src] ++ Config.get([:http_security, :csp_policy, :script_src])
|
||||
script_src = [script_src | get_csp_config(:script_src)]
|
||||
|
||||
style_src =
|
||||
["style-src 'self' 'unsafe-inline' "] ++
|
||||
Config.get([:http_security, :csp_policy, :style_src])
|
||||
style_src = [@style_src | get_csp_config(:style_src)]
|
||||
|
||||
font_src = ["font-src 'self' "] ++ Config.get([:http_security, :csp_policy, :font_src])
|
||||
font_src = [@font_src | get_csp_config(:font_src)]
|
||||
|
||||
frame_src = if Config.get(:env) == :dev, do: "frame-src 'self' ", else: "frame-src 'none' "
|
||||
frame_src = [frame_src] ++ Config.get([:http_security, :csp_policy, :frame_src])
|
||||
frame_src = [frame_src | get_csp_config(:frame_src)]
|
||||
|
||||
frame_ancestors =
|
||||
if Config.get(:env) == :dev, do: "frame-ancestors 'self' ", else: "frame-ancestors 'none' "
|
||||
|
||||
frame_ancestors =
|
||||
[frame_ancestors] ++ Config.get([:http_security, :csp_policy, :frame_ancestors])
|
||||
frame_ancestors = [frame_ancestors | get_csp_config(:frame_ancestors)]
|
||||
|
||||
insecure = if scheme == "https", do: "upgrade-insecure-requests"
|
||||
|
||||
@ -93,7 +109,7 @@ defmodule Mobilizon.Web.Plugs.HTTPSecurityPlug do
|
||||
|> add_csp_param(frame_src)
|
||||
|> add_csp_param(frame_ancestors)
|
||||
|> add_csp_param(insecure)
|
||||
|> :erlang.iolist_to_binary()
|
||||
|> to_string()
|
||||
end
|
||||
|
||||
defp add_csp_param(csp_iodata, nil), do: csp_iodata
|
||||
@ -109,4 +125,7 @@ defmodule Mobilizon.Web.Plugs.HTTPSecurityPlug do
|
||||
end
|
||||
|
||||
defp maybe_send_sts_header(conn, _), do: conn
|
||||
|
||||
defp get_csp_config(type),
|
||||
do: [:http_security, :csp_policy, type] |> Config.get() |> Enum.join(" ")
|
||||
end
|
||||
|
2
mix.exs
2
mix.exs
@ -119,7 +119,7 @@ defmodule Mobilizon.Mixfile do
|
||||
{:http_sign, "~> 0.1.1"},
|
||||
{:ecto_enum, "~> 1.4"},
|
||||
{:ex_ical, "~> 0.2"},
|
||||
{:bamboo, "~> 2.0"},
|
||||
{:bamboo, "~> 2.1", override: true},
|
||||
{:bamboo_phoenix, "~> 1.0"},
|
||||
{:bamboo_smtp, "~> 4.0"},
|
||||
{:geolix, "~> 2.0"},
|
||||
|
18
mix.lock
18
mix.lock
@ -1,10 +1,10 @@
|
||||
%{
|
||||
"absinthe": {:hex, :absinthe, "1.6.3", "f8c7a581fa2382bde1adadd405f5caf6597623b48d160367f759d0d6e6292f84", [:mix], [{:dataloader, "~> 1.0.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4a11192165fb3b7566ffdd86eccd12f0a87158b0b18c00e0400899e8df0225ea"},
|
||||
"absinthe_phoenix": {:hex, :absinthe_phoenix, "2.0.1", "112cb3468db2748a85bd8bd3f4d6d33f37408a96cb170077026ace96ddb1bab2", [:mix], [{:absinthe, "~> 1.5", [hex: :absinthe, repo: "hexpm", optional: false]}, {:absinthe_plug, "~> 1.5", [hex: :absinthe_plug, repo: "hexpm", optional: false]}, {:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.5", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.13", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}], "hexpm", "e773adc876fbc84fb05a82e125d9c263f129520b36e5576554ffcb8cf49db445"},
|
||||
"absinthe_plug": {:hex, :absinthe_plug, "1.5.6", "be33fb0b883dd6d43d206de04b8b9a378529589ec66fe639c5f2aa0ec96ca595", [:mix], [{:absinthe, "~> 1.5", [hex: :absinthe, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "b589cdfeba5b0bebe32fa4789fb4dcb86907d6bf6f037a4c67e2ca844b297d29"},
|
||||
"absinthe_plug": {:hex, :absinthe_plug, "1.5.7", "c9954c5eff0a11be185f73987533d38d6aa44ca6bd5253de32de099f82996ce5", [:mix], [{:absinthe, "~> 1.5", [hex: :absinthe, repo: "hexpm", optional: false]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "2e7d766c5b3ec57aed06db0d420674bc0ff6998c55c85f5fb9bb0d3dcf7ad20d"},
|
||||
"argon2_elixir": {:hex, :argon2_elixir, "2.4.0", "2a22ea06e979f524c53b42b598fc6ba38cdcbc977a155e33e057732cfb1fb311", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "4ea82e183cf8e7f66dab1f767fedcfe6a195e140357ef2b0423146b72e0a551d"},
|
||||
"atomex": {:hex, :atomex, "0.4.1", "7d3910ff7795db91b9af9f8d3e65af7ac69f235adf03484995fc667a36f3edc5", [:mix], [{:xml_builder, "~> 2.1", [hex: :xml_builder, repo: "hexpm", optional: false]}], "hexpm", "f3ac737f7493d42cfddf917f3ac49d60e0a0cf1a35c0712851b07fe8c0a05c7a"},
|
||||
"bamboo": {:hex, :bamboo, "2.0.2", "0e2914d2bea0de3b1743384c24ffbe20fbb58094376a49f1cf5d9ed9959abd82", [:mix], [{:hackney, ">= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.4", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "058d57cf4fcdac19413aa72732eb43c88954fb151a1cb6a382014e0cddbf6314"},
|
||||
"bamboo": {:hex, :bamboo, "2.1.0", "3c58f862efd74fa8c8d48a410ac592b41f7d24785e828566f7a0af549269ddc3", [:mix], [{:hackney, ">= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.4", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "f0ad2623b9a1d2dc06dcf289b59df9ebc522f49f3a21971ec87a8fce04e6d33e"},
|
||||
"bamboo_phoenix": {:hex, :bamboo_phoenix, "1.0.0", "f3cc591ffb163ed0bf935d256f1f4645cd870cf436545601215745fb9cc9953f", [:mix], [{:bamboo, ">= 2.0.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.3.0", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "6db88fbb26019c84a47994bb2bd879c0887c29ce6c559bc6385fd54eb8b37dee"},
|
||||
"bamboo_smtp": {:hex, :bamboo_smtp, "4.0.0", "0cc7df161d5d440d280a6d2eb20bf80bc45ea77161728a229e5ab339dcd087cd", [:mix], [{:bamboo, "~> 2.0.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:gen_smtp, "~> 1.1.0", [hex: :gen_smtp, repo: "hexpm", optional: false]}], "hexpm", "2412015092121b9f24f3f2e654bcd98e5c5f9afb323a94f8defa22e70ba8f23d"},
|
||||
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
|
||||
@ -25,18 +25,18 @@
|
||||
"dialyxir": {:hex, :dialyxir, "1.1.0", "c5aab0d6e71e5522e77beff7ba9e08f8e02bad90dfbeffae60eaf0cb47e29488", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "07ea8e49c45f15264ebe6d5b93799d4dd56a44036cf42d0ad9c960bc266c0b9a"},
|
||||
"earmark": {:hex, :earmark, "1.4.14", "d04572cef64dd92726a97d92d714e38d6e130b024ea1b3f8a56e7de66ec04e50", [:mix], [{:earmark_parser, ">= 1.4.12", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "df338b8b1852ee425180b276c56c6941cb12220e04fe8718fe4acbdd35fd699f"},
|
||||
"earmark_parser": {:hex, :earmark_parser, "1.4.12", "b245e875ec0a311a342320da0551da407d9d2b65d98f7a9597ae078615af3449", [:mix], [], "hexpm", "711e2cc4d64abb7d566d43f54b78f7dc129308a63bc103fbd88550d2174b3160"},
|
||||
"ecto": {:hex, :ecto, "3.6.0", "df6b00f7278b458108044da4cff365dde31f6f2f621cf7dc0bf857b26be3bd20", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3035603f5b308ea7731b854493e5b5c1565e4d1e073186c3963b9689304f1d08"},
|
||||
"ecto": {:hex, :ecto, "3.6.1", "7bb317e3fd0179ad725069fd0fe8a28ebe48fec6282e964ea502e4deccb0bd0f", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cbb3294a990447b19f0725488a749f8cf806374e0d9d0dffc45d61e7aeaf6553"},
|
||||
"ecto_autoslug_field": {:hex, :ecto_autoslug_field, "2.0.1", "2177c1c253f6dd3efd4b56d1cb76104d0a6ef044c6b9a7a0ad6d32665c4111e5", [:mix], [{:ecto, ">= 2.1.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:slugger, ">= 0.2.0", [hex: :slugger, repo: "hexpm", optional: false]}], "hexpm", "a3cc73211f2e75b89a03332183812ebe1ac08be2e25a1df5aa3d1422f92c45c3"},
|
||||
"ecto_enum": {:hex, :ecto_enum, "1.4.0", "d14b00e04b974afc69c251632d1e49594d899067ee2b376277efd8233027aec8", [:mix], [{:ecto, ">= 3.0.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "> 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:mariaex, ">= 0.0.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "8fb55c087181c2b15eee406519dc22578fa60dd82c088be376d0010172764ee4"},
|
||||
"ecto_shortuuid": {:hex, :ecto_shortuuid, "0.1.3", "d36aede64edf256e4b769be2ad15a8ad5d9d1ff8ad46befe39e8cb4489abcd05", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:shortuuid, "~> 2.1.1", [hex: :shortuuid, repo: "hexpm", optional: false]}], "hexpm", "d215c8ced7125265de94d55abc696125942caef33439cf281fafded9744a4294"},
|
||||
"ecto_sql": {:hex, :ecto_sql, "3.6.0", "5cb277b086618a644f2c5450316202a885716bb7726b9f13b74cb0708bea3a8f", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.6.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.4.0 or ~> 0.5.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3486d6e29ee4a0e7a381390c9c289bfbbaf5dc1971e269c579799d2300e5bd5"},
|
||||
"ecto_sql": {:hex, :ecto_sql, "3.6.1", "8774dc3fc0ff7b6be510858b99883640f990c0736b8ab54588f9a0c91807f909", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.6.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.4.0 or ~> 0.5.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "66f35c3f2d5978b6bffebd1e6351ab8c9d6b68650d62abd1ab8d149de40e0779"},
|
||||
"elixir_feed_parser": {:hex, :elixir_feed_parser, "2.1.0", "bb96fb6422158dc7ad59de62ef211cc69d264acbbe63941a64a5dce97bbbc2e6", [:mix], [{:timex, "~> 3.4", [hex: :timex, repo: "hexpm", optional: false]}], "hexpm", "2d3c62fe7b396ee3b73d7160bc8fadbd78bfe9597c98c7d79b3f1038d9cba28f"},
|
||||
"elixir_make": {:hex, :elixir_make, "0.6.2", "7dffacd77dec4c37b39af867cedaabb0b59f6a871f89722c25b28fcd4bd70530", [:mix], [], "hexpm", "03e49eadda22526a7e5279d53321d1cced6552f344ba4e03e619063de75348d9"},
|
||||
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
|
||||
"erlsom": {:hex, :erlsom, "1.5.0", "c5a5cdd0ee0e8dca62bcc4b13ff08da24fdefc16ccd8b25282a2fda2ba1be24a", [:rebar3], [], "hexpm", "55a9dbf9cfa77fcfc108bd8e2c4f9f784dea228a8f4b06ea10b684944946955a"},
|
||||
"eternal": {:hex, :eternal, "1.2.2", "d1641c86368de99375b98d183042dd6c2b234262b8d08dfd72b9eeaafc2a1abd", [:mix], [], "hexpm", "2c9fe32b9c3726703ba5e1d43a1d255a4f3f2d8f8f9bc19f094c7cb1a7a9e782"},
|
||||
"ex_cldr": {:hex, :ex_cldr, "2.20.0", "571a4b490c333809be59cc984a21be2deaab1db9e2418e323d5935aec8b1394a", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.5", [hex: :certifi, repo: "hexpm", optional: true]}, {:cldr_utils, "~> 2.15", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:gettext, "~> 0.13", [hex: :gettext, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "06147e4a27be62e6fe92db14cf5048c645927bfc530aa1cc6af8c92d65e32427"},
|
||||
"ex_cldr_calendars": {:hex, :ex_cldr_calendars, "1.13.0", "6bea6f3c54d74c0ed131dd17e1cff68e02b7053f24c2fac91f129e5221ff723a", [:mix], [{:calendar_interval, "~> 0.2", [hex: :calendar_interval, repo: "hexpm", optional: true]}, {:earmark, "~> 1.0", [hex: :earmark, repo: "hexpm", optional: false]}, {:ex_cldr_numbers, "~> 2.17", [hex: :ex_cldr_numbers, repo: "hexpm", optional: false]}, {:ex_cldr_units, "~> 3.5", [hex: :ex_cldr_units, repo: "hexpm", optional: true]}, {:ex_doc, "~> 0.21", [hex: :ex_doc, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "d07ab6b2164b6a0861de6ecb600747aab61c94a0b9c001e36c2e0b731eeb567a"},
|
||||
"ex_cldr_calendars": {:hex, :ex_cldr_calendars, "1.14.0", "e1d1a6a0e9d594bc0da4f2881c9b0fac822075f5e2bfdba3ef5edf1a0a66abac", [:mix], [{:calendar_interval, "~> 0.2", [hex: :calendar_interval, repo: "hexpm", optional: true]}, {:earmark, "~> 1.0", [hex: :earmark, repo: "hexpm", optional: false]}, {:ex_cldr_numbers, "~> 2.17", [hex: :ex_cldr_numbers, repo: "hexpm", optional: false]}, {:ex_cldr_units, "~> 3.5", [hex: :ex_cldr_units, repo: "hexpm", optional: true]}, {:ex_doc, "~> 0.21", [hex: :ex_doc, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "6f95e8350b00aedb26610fd461803993efe737bc535bfbf8cce4c7f66944648c"},
|
||||
"ex_cldr_currencies": {:hex, :ex_cldr_currencies, "2.9.1", "692d9d8262bd9c423d601d5ce6ae294df85f8652664e723e2cfd68d97bd72a10", [:mix], [{:ex_cldr, "~> 2.20", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:ex_doc, "~> 0.18", [hex: :ex_doc, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "1bc6f9eabef1e79e98cb9f8b14dc5657c17ddcbea31e800440fd52a6e45e20ac"},
|
||||
"ex_cldr_dates_times": {:hex, :ex_cldr_dates_times, "2.7.0", "c8fc77e075e7408fd414b2a4396e2023901032a3c20d94035b8cee54a10f28c9", [:mix], [{:calendar_interval, "~> 0.2", [hex: :calendar_interval, repo: "hexpm", optional: true]}, {:ex_cldr_calendars, "~> 1.13", [hex: :ex_cldr_calendars, repo: "hexpm", optional: false]}, {:ex_cldr_numbers, "~> 2.17", [hex: :ex_cldr_numbers, repo: "hexpm", optional: false]}, {:ex_doc, "~> 0.18", [hex: :ex_doc, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "e21e8c6f9440c91d6111cb39ac96a423d833206ce8d1b24bbdeddd12b2b9427d"},
|
||||
"ex_cldr_languages": {:hex, :ex_cldr_languages, "0.2.2", "d7dab93272443b70e18e6aef0f62974418baaca3a3b31a66d51921ec1547113c", [:mix], [{:ex_cldr, "~> 2.2 and >= 2.2.1", [hex: :ex_cldr, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "d9cbf4bf643365b0042e774520ddfcbc31618efd5a5383fac98f75149961622c"},
|
||||
@ -58,8 +58,8 @@
|
||||
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
|
||||
"floki": {:hex, :floki, "0.30.1", "75d35526d3a1459920b6e87fdbc2e0b8a3670f965dd0903708d2b267e0904c55", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "e9c03524447d1c4cbfccd672d739b8c18453eee377846b119d4fd71b1a176bb8"},
|
||||
"gen_smtp": {:hex, :gen_smtp, "1.1.1", "bf9303c31735100631b1d708d629e4c65944319d1143b5c9952054f4a1311d85", [:rebar3], [{:hut, "1.3.0", [hex: :hut, repo: "hexpm", optional: false]}, {:ranch, ">= 1.7.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "51bc50cc017efd4a4248cbc39ea30fb60efa7d4a49688986fafad84434ff9ab7"},
|
||||
"geo": {:hex, :geo, "3.3.8", "ea52f985960089c5a278a93cba4de973971de2bd4e407b74f56455d6824e1b8a", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "55c206b113b5ff2e766c4c03643165c4c388dc09502a557334c26d9e15fb4acd"},
|
||||
"geo_postgis": {:hex, :geo_postgis, "3.3.1", "45bc96b9121d0647341685dc9d44956d61338707482d655c803500676b0413a1", [:mix], [{:geo, "~> 3.3", [hex: :geo, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0 or ~> 4.0", [hex: :poison, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.14", [hex: :postgrex, repo: "hexpm", optional: false]}], "hexpm", "3c3957d8750e3effd565f068ee658ef0e881f9a07084a23f6c5ef8262d09b8e9"},
|
||||
"geo": {:hex, :geo, "3.4.2", "834f106e4ba072f5917920bd7ece42cfe1caa03c7fb278f85ea5d0905c8dc153", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "0a9fdad0d5197678cbac85e1dac674528bd90fa923398679a174b541cdf0ec68"},
|
||||
"geo_postgis": {:hex, :geo_postgis, "3.4.0", "67815cc9b3db12e378e7a96d0f77d3bc2188534aba4d2c2229e3ebf8370f9d52", [:mix], [{:geo, "~> 3.4", [hex: :geo, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0 or ~> 4.0", [hex: :poison, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.0.0", [hex: :postgrex, repo: "hexpm", optional: false]}], "hexpm", "23563946ef6e5c747380e6a7a0493b0a631e91d0452314ee7e33354f4fdf5230"},
|
||||
"geohax": {:hex, :geohax, "0.4.1", "87efd3c4bb00d9dd237cef917004b635417859f51dfe716ba0864b8c61eb7e0e", [:mix], [], "hexpm", "ce6aff24726f3824caf59aa8b903a1be99ac05820b53c23196d5ac36b13a1fa3"},
|
||||
"geolix": {:hex, :geolix, "2.0.0", "7e65764bedfc98d08a3ddb24c417657c9d438eff163280b45fbb7de289626acd", [:mix], [], "hexpm", "8742bf588ed0bb7def2c443204d09d355990846c6efdff96ded66aac24c301df"},
|
||||
"geolix_adapter_mmdb2": {:hex, :geolix_adapter_mmdb2, "0.6.0", "6ab9dbf6ea395817aa1fd2597be25d0dda1853c7f664e62716e47728d18bc4f9", [:mix], [{:geolix, "~> 2.0", [hex: :geolix, repo: "hexpm", optional: false]}, {:mmdb2_decoder, "~> 3.0", [hex: :mmdb2_decoder, repo: "hexpm", optional: false]}], "hexpm", "06ff962feae8a310cffdf86b74bfcda6e2d0dccb439bb1f62df2b657b1c0269b"},
|
||||
@ -105,7 +105,7 @@
|
||||
"phoenix": {:hex, :phoenix, "1.5.8", "71cfa7a9bb9a37af4df98939790642f210e35f696b935ca6d9d9c55a884621a4", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "35ded0a32f4836168c7ab6c33b88822eccd201bcd9492125a9bea4c54332d955"},
|
||||
"phoenix_ecto": {:hex, :phoenix_ecto, "4.2.1", "13f124cf0a3ce0f1948cf24654c7b9f2347169ff75c1123f44674afee6af3b03", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 2.15", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "478a1bae899cac0a6e02be1deec7e2944b7754c04e7d4107fc5a517f877743c0"},
|
||||
"phoenix_html": {:hex, :phoenix_html, "2.14.3", "51f720d0d543e4e157ff06b65de38e13303d5778a7919bcc696599e5934271b8", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "efd697a7fff35a13eeeb6b43db884705cba353a1a41d127d118fda5f90c8e80f"},
|
||||
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.3.0", "f35f61c3f959c9a01b36defaa1f0624edd55b87e236b606664a556d6f72fd2e7", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "02c1007ae393f2b76ec61c1a869b1e617179877984678babde131d716f95b582"},
|
||||
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.3.1", "9eba6ad16bd80c45f338b2059c7b255ce30784d76f4181304e7b78640e5a7513", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "f3ae26b5abb85a1cb2bc8bb199e29fbcefb34259e469b31fe0c6323f2175a5ef"},
|
||||
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"},
|
||||
"plug": {:hex, :plug, "1.11.1", "f2992bac66fdae679453c9e86134a4201f6f43a687d8ff1cd1b2862d53c80259", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "23524e4fefbb587c11f0833b3910bfb414bf2e2534d61928e920f54e3a1b881f"},
|
||||
"plug_cowboy": {:hex, :plug_cowboy, "2.4.1", "779ba386c0915027f22e14a48919a9545714f849505fa15af2631a0d298abf0f", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d72113b6dff7b37a7d9b2a5b68892808e3a9a752f2bf7e503240945385b70507"},
|
||||
@ -124,7 +124,7 @@
|
||||
"sobelow": {:hex, :sobelow, "0.11.1", "23438964486f8112b41e743bbfd402da3e5b296fdc9eacab29914b79c48916dd", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "9897363a7eff96f4809304a90aad819e2ad5e5d24db547af502885146746a53c"},
|
||||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
|
||||
"sweet_xml": {:hex, :sweet_xml, "0.6.6", "fc3e91ec5dd7c787b6195757fbcf0abc670cee1e4172687b45183032221b66b8", [:mix], [], "hexpm", "2e1ec458f892ffa81f9f8386e3f35a1af6db7a7a37748a64478f13163a1f3573"},
|
||||
"telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},
|
||||
"telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"},
|
||||
"tesla": {:hex, :tesla, "1.4.1", "ff855f1cac121e0d16281b49e8f066c4a0d89965f98864515713878cca849ac8", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.3", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, "~> 1.3", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "~> 4.4.0", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "95f5de35922c8c4b3945bee7406f66eb680b0955232f78f5fb7e853aa1ce201a"},
|
||||
"timex": {:hex, :timex, "3.7.5", "3eca56e23bfa4e0848f0b0a29a92fa20af251a975116c6d504966e8a90516dfd", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 1.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "a15608dca680f2ef663d71c95842c67f0af08a0f3b1d00e17bbd22872e2874e4"},
|
||||
"tzdata": {:hex, :tzdata, "1.1.0", "72f5babaa9390d0f131465c8702fa76da0919e37ba32baa90d93c583301a8359", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "18f453739b48d3dc5bcf0e8906d2dc112bb40baafe2c707596d89f3c8dd14034"},
|
||||
|
@ -3,7 +3,7 @@
|
||||
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Mobilizon.Web.Plug.FederatingTest do
|
||||
defmodule Mobilizon.Web.Plugs.FederatingTest do
|
||||
use Mobilizon.Web.ConnCase
|
||||
|
||||
alias Mobilizon.Web.Plugs.Federating
|
||||
|
93
test/web/plugs/http_security_plug_test.exs
Normal file
93
test/web/plugs/http_security_plug_test.exs
Normal file
@ -0,0 +1,93 @@
|
||||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Mobilizon.Web.Plugs.HTTPSecurityPlugTest do
|
||||
use Mobilizon.Web.ConnCase
|
||||
use Mobilizon.Tests.Helpers
|
||||
|
||||
alias Plug.Conn
|
||||
|
||||
describe "http security enabled" do
|
||||
setup do: clear_config([:http_security, :enabled], true)
|
||||
|
||||
test "it sends CSP headers when enabled", %{conn: conn} do
|
||||
conn = post(conn, "/api")
|
||||
|
||||
refute Conn.get_resp_header(conn, "x-xss-protection") == []
|
||||
refute Conn.get_resp_header(conn, "x-frame-options") == []
|
||||
refute Conn.get_resp_header(conn, "x-content-type-options") == []
|
||||
refute Conn.get_resp_header(conn, "referrer-policy") == []
|
||||
refute Conn.get_resp_header(conn, "content-security-policy") == []
|
||||
end
|
||||
|
||||
test "it sends STS headers when enabled", %{conn: conn} do
|
||||
clear_config([:http_security, :sts], true)
|
||||
|
||||
conn = post(conn, "/api")
|
||||
|
||||
refute Conn.get_resp_header(conn, "strict-transport-security") == []
|
||||
end
|
||||
|
||||
test "it does not send STS headers when disabled", %{conn: conn} do
|
||||
clear_config([:http_security, :sts], false)
|
||||
|
||||
conn = post(conn, "/api")
|
||||
|
||||
assert Conn.get_resp_header(conn, "strict-transport-security") == []
|
||||
end
|
||||
|
||||
test "referrer-policy header reflects configured value", %{conn: conn} do
|
||||
resp = post(conn, "/api")
|
||||
|
||||
assert Conn.get_resp_header(resp, "referrer-policy") == ["same-origin"]
|
||||
|
||||
clear_config([:http_security, :referrer_policy], "no-referrer")
|
||||
|
||||
resp = post(conn, "/api")
|
||||
|
||||
assert Conn.get_resp_header(resp, "referrer-policy") == ["no-referrer"]
|
||||
end
|
||||
|
||||
test "default values for content-security-policy are always included", %{conn: conn} do
|
||||
conn = post(conn, "/api")
|
||||
|
||||
[csp] = Conn.get_resp_header(conn, "content-security-policy")
|
||||
assert csp =~ "media-src 'self'"
|
||||
assert csp =~ "img-src 'self' data: blob: *.tile.openstreetmap.org"
|
||||
assert csp =~ "frame-src 'none'"
|
||||
assert csp =~ "frame-ancestors 'none'"
|
||||
assert csp =~ "font-src 'self'"
|
||||
end
|
||||
end
|
||||
|
||||
describe "custom csp config" do
|
||||
test "it doesn't override default values", %{conn: conn} do
|
||||
clear_config([:http_security, :csp_policy, :script_src], [
|
||||
"example.com",
|
||||
"matomo.example.com"
|
||||
])
|
||||
|
||||
conn = post(conn, "/api")
|
||||
|
||||
[csp] = Conn.get_resp_header(conn, "content-security-policy")
|
||||
|
||||
assert csp =~
|
||||
~r/script-src 'self' 'unsafe-eval' 'unsafe-inline' 'sha256-[\w+\/=]*' example.com matomo.example.com;/
|
||||
end
|
||||
end
|
||||
|
||||
test "it does not send CSP headers when disabled", %{conn: conn} do
|
||||
clear_config([:http_security, :enabled], false)
|
||||
|
||||
conn = post(conn, "/api")
|
||||
|
||||
assert Conn.get_resp_header(conn, "x-xss-protection") == []
|
||||
assert Conn.get_resp_header(conn, "x-permitted-cross-domain-policies") == []
|
||||
assert Conn.get_resp_header(conn, "x-frame-options") == []
|
||||
assert Conn.get_resp_header(conn, "x-content-type-options") == []
|
||||
assert Conn.get_resp_header(conn, "x-download-options") == []
|
||||
assert Conn.get_resp_header(conn, "referrer-policy") == []
|
||||
assert Conn.get_resp_header(conn, "content-security-policy") == []
|
||||
end
|
||||
end
|
@ -1,4 +1,4 @@
|
||||
defmodule Mobilizon.Web.Plug.HTTPSignaturesTest do
|
||||
defmodule Mobilizon.Web.Plugs.HTTPSignaturesTest do
|
||||
use Mobilizon.Web.ConnCase
|
||||
import Mock
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user