mirror of
https://github.com/wassname/Open-Assistant.git
synced 2026-08-13 11:50:37 +08:00
Add ToS/License Agreement to Website (#1080)
* add new apis to oasst client * add tos handler * Add ToS to Dashboard * use Provider for ToS * simplify provider * fix error * Inject into JWT * primitive error handling * update comment * address review
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"title": "Terms of Service for Open Assistant",
|
||||
"content": "To continue using Open Assistant, you have to accept our Terms of Service first.",
|
||||
"accept": "Accept",
|
||||
"decline": "Decline"
|
||||
}
|
||||
@@ -19,10 +19,10 @@ export const PolicyChapterCard = ({ chapter, children }: ChapterProps) => {
|
||||
<Stack spacing="4">
|
||||
<Stack>
|
||||
<Flex alignItems="end" gap="2">
|
||||
<Text as="b" fontSize="xl" color="blue.500">
|
||||
<Text as="b" fontSize="md" color="blue.500">
|
||||
{chapter.number}
|
||||
</Text>
|
||||
<Heading as="h3" size="lg">
|
||||
<Heading as="h3" size="md">
|
||||
{chapter.title}
|
||||
</Heading>
|
||||
</Flex>
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
import { Box, BoxProps, useColorModeValue } from "@chakra-ui/react";
|
||||
import clsx from "clsx";
|
||||
import { PropsWithChildren } from "react";
|
||||
import { useMemo } from "react";
|
||||
|
||||
export const SurveyCard = (props: PropsWithChildren<{ className?: string }>) => {
|
||||
export const SurveyCard = (props: BoxProps) => {
|
||||
const backgroundColor = useColorModeValue("white", "gray.700");
|
||||
|
||||
const BoxClasses: BoxProps = {
|
||||
gap: "2",
|
||||
borderRadius: "xl",
|
||||
shadow: "base",
|
||||
className: clsx("p-4 sm:p-6", props.className),
|
||||
};
|
||||
const boxProps: BoxProps = useMemo(
|
||||
() => ({
|
||||
gap: "2",
|
||||
borderRadius: "xl",
|
||||
shadow: "base",
|
||||
...props,
|
||||
className: clsx("p-4 sm:p-6", props.className),
|
||||
}),
|
||||
[props]
|
||||
);
|
||||
|
||||
return (
|
||||
<Box as="section" bg={backgroundColor} {...BoxClasses}>
|
||||
<Box as="section" bg={backgroundColor} {...boxProps}>
|
||||
{props.children}
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import { Flex, Text } from "@chakra-ui/react";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { useTranslation } from "next-i18next";
|
||||
import { ReactNode, useMemo } from "react";
|
||||
import { SubmitButton } from "src/components/Buttons/Submit";
|
||||
import { SurveyCard } from "src/components/Survey/SurveyCard";
|
||||
import { post } from "src/lib/api";
|
||||
import { TermsOfService } from "src/pages/terms-of-service";
|
||||
|
||||
const navigateAway = () => {
|
||||
location.href = "https://laion.ai/";
|
||||
};
|
||||
|
||||
const acceptToS = async () => {
|
||||
await post("/api/tos", { arg: {} });
|
||||
location.reload();
|
||||
};
|
||||
|
||||
export const ToSWrapper = ({ children }: { children?: ReactNode | undefined }) => {
|
||||
const { t } = useTranslation("tos");
|
||||
const { data: session, status } = useSession();
|
||||
const hasAcceptedTos = Boolean(session?.user.tosAcceptanceDate);
|
||||
const isLoading = status === "loading";
|
||||
|
||||
const contents = useMemo(
|
||||
() => (
|
||||
<SurveyCard display="flex" flexDir="column" w="full" maxWidth="7xl" m="auto" gap={4}>
|
||||
<Text fontWeight="bold" fontSize="xl" as="h2">
|
||||
{t("title")}
|
||||
</Text>
|
||||
<Text>{t("content")}</Text>
|
||||
<TermsOfService />
|
||||
<Flex gap={10} justifyContent="center">
|
||||
<SubmitButton onClick={navigateAway} colorScheme="red">
|
||||
{t("decline")}
|
||||
</SubmitButton>
|
||||
<SubmitButton onClick={acceptToS} colorScheme="blue">
|
||||
{t("accept")}
|
||||
</SubmitButton>
|
||||
</Flex>
|
||||
</SurveyCard>
|
||||
),
|
||||
[t]
|
||||
);
|
||||
|
||||
if (isLoading || hasAcceptedTos) {
|
||||
return <>{children}</>;
|
||||
}
|
||||
return contents;
|
||||
};
|
||||
@@ -13,6 +13,10 @@ export class OasstError {
|
||||
this.errorCode = errorCode;
|
||||
this.httpStatusCode = httpStatusCode;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return JSON.stringify(this);
|
||||
}
|
||||
}
|
||||
|
||||
export class OasstApiClient {
|
||||
@@ -30,12 +34,66 @@ export class OasstApiClient {
|
||||
}
|
||||
}
|
||||
|
||||
fetch_full_settings() {
|
||||
return this.get<Record<string, any>>("/api/v1/admin/backend_settings/full");
|
||||
private async request<T>(
|
||||
method: "GET" | "POST" | "PUT" | "DELETE",
|
||||
path: string,
|
||||
init?: RequestInit
|
||||
): Promise<T | null> {
|
||||
const resp = await fetch(`${this.oasstApiUrl}${path}`, {
|
||||
method,
|
||||
...init,
|
||||
headers: {
|
||||
...init?.headers,
|
||||
...this.userHeaders,
|
||||
"X-API-Key": this.oasstApiKey,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
if (resp.status === 204) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (resp.status >= 300) {
|
||||
const errorText = await resp.text();
|
||||
let error;
|
||||
try {
|
||||
error = JSON.parse(errorText);
|
||||
} catch (e) {
|
||||
throw new OasstError(errorText, 0, resp.status);
|
||||
}
|
||||
throw new OasstError(error.message ?? error, error.error_code, resp.status);
|
||||
}
|
||||
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
fetch_public_settings() {
|
||||
return this.get<Record<string, any>>("/api/v1/admin/backend_settings/public");
|
||||
private async post<T>(path: string, body: unknown) {
|
||||
return this.request<T>("POST", path, {
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
}
|
||||
|
||||
private async put<T>(path: string) {
|
||||
return this.request<T>("PUT", path);
|
||||
}
|
||||
|
||||
private async get<T>(path: string, query?: Record<string, string | number | boolean | undefined>) {
|
||||
if (!query) {
|
||||
return this.request<T>("GET", path);
|
||||
}
|
||||
|
||||
const filteredQuery = Object.fromEntries(
|
||||
Object.entries(query).filter(([, value]) => value !== undefined)
|
||||
) as Record<string, string>;
|
||||
|
||||
const params = new URLSearchParams(filteredQuery).toString();
|
||||
|
||||
return this.request<T>("GET", `${path}?${params}`);
|
||||
}
|
||||
|
||||
private async delete<T>(path: string) {
|
||||
return this.request<T>("DELETE", path);
|
||||
}
|
||||
|
||||
// TODO return a strongly typed Task?
|
||||
@@ -50,15 +108,11 @@ export class OasstApiClient {
|
||||
}
|
||||
|
||||
async ackTask(taskId: string, messageId: string): Promise<null> {
|
||||
return this.post(`/api/v1/tasks/${taskId}/ack`, {
|
||||
message_id: messageId,
|
||||
});
|
||||
return this.post(`/api/v1/tasks/${taskId}/ack`, { message_id: messageId });
|
||||
}
|
||||
|
||||
async nackTask(taskId: string, reason: string): Promise<null> {
|
||||
return this.post(`/api/v1/tasks/${taskId}/nack`, {
|
||||
reason,
|
||||
});
|
||||
return this.post(`/api/v1/tasks/${taskId}/nack`, { reason });
|
||||
}
|
||||
|
||||
// TODO return a strongly typed Task?
|
||||
@@ -84,6 +138,14 @@ export class OasstApiClient {
|
||||
});
|
||||
}
|
||||
|
||||
fetch_full_settings() {
|
||||
return this.get<Record<string, any>>("/api/v1/admin/backend_settings/full");
|
||||
}
|
||||
|
||||
fetch_public_settings() {
|
||||
return this.get<Record<string, any>>("/api/v1/admin/backend_settings/public");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tasks availability information for given `user`.
|
||||
*/
|
||||
@@ -208,68 +270,6 @@ export class OasstApiClient {
|
||||
});
|
||||
}
|
||||
|
||||
private async post<T>(path: string, body: unknown) {
|
||||
return this.request<T>("POST", path, {
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
}
|
||||
|
||||
private async put<T>(path: string) {
|
||||
return this.request<T>("PUT", path);
|
||||
}
|
||||
|
||||
private async delete<T>(path: string) {
|
||||
return this.request<T>("DELETE", path);
|
||||
}
|
||||
|
||||
private async get<T>(path: string, query?: Record<string, string | number | boolean | undefined>) {
|
||||
if (!query) {
|
||||
return this.request<T>("GET", path);
|
||||
}
|
||||
|
||||
const filteredQuery = Object.fromEntries(
|
||||
Object.entries(query).filter(([, value]) => value !== undefined)
|
||||
) as Record<string, string>;
|
||||
|
||||
const params = new URLSearchParams(filteredQuery).toString();
|
||||
|
||||
return this.request<T>("GET", `${path}?${params}`);
|
||||
}
|
||||
|
||||
private async request<T>(
|
||||
method: "GET" | "POST" | "PUT" | "DELETE",
|
||||
path: string,
|
||||
init?: RequestInit
|
||||
): Promise<T | null> {
|
||||
const resp = await fetch(`${this.oasstApiUrl}${path}`, {
|
||||
method,
|
||||
...init,
|
||||
headers: {
|
||||
...init?.headers,
|
||||
...this.userHeaders,
|
||||
"X-API-Key": this.oasstApiKey,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
if (resp.status === 204) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (resp.status >= 300) {
|
||||
const errorText = await resp.text();
|
||||
let error;
|
||||
try {
|
||||
error = JSON.parse(errorText);
|
||||
} catch (e) {
|
||||
throw new OasstError(errorText, 0, resp.status);
|
||||
}
|
||||
throw new OasstError(error.message ?? error, error.error_code, resp.status);
|
||||
}
|
||||
|
||||
return await resp.json();
|
||||
}
|
||||
|
||||
fetch_my_messages(user: BackendUserCore) {
|
||||
const params = new URLSearchParams({
|
||||
username: user.id,
|
||||
@@ -289,4 +289,16 @@ export class OasstApiClient {
|
||||
fetch_conversation(messageId: string) {
|
||||
return this.get(`/api/v1/messages/${messageId}/conversation`);
|
||||
}
|
||||
|
||||
async fetch_tos_acceptance(user: BackendUserCore): Promise<BackendUser["tos_acceptance_date"]> {
|
||||
const backendUser = await this.get<BackendUser>(`/api/v1/frontend_users/${user.auth_method}/${user.id}`);
|
||||
return backendUser.tos_acceptance_date;
|
||||
}
|
||||
|
||||
async set_tos_acceptance(user: BackendUserCore) {
|
||||
// TODO: it is wasteful having to get the backend user first and then set the tos status
|
||||
// is there a better way of doing this?
|
||||
const backendUser = await this.get<BackendUser>(`/api/v1/frontend_users/${user.auth_method}/${user.id}`);
|
||||
await this.put<void>(`/api/v1/users/${backendUser.user_id}?tos_acceptance=true`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,9 @@ import CredentialsProvider from "next-auth/providers/credentials";
|
||||
import DiscordProvider from "next-auth/providers/discord";
|
||||
import EmailProvider from "next-auth/providers/email";
|
||||
import { checkCaptcha } from "src/lib/captcha";
|
||||
import { createApiClientFromUser } from "src/lib/oasst_client_factory";
|
||||
import prisma from "src/lib/prismadb";
|
||||
import { BackendUserCore } from "src/types/Users";
|
||||
import { generateUsername } from "unique-username-generator";
|
||||
|
||||
const providers: Provider[] = [];
|
||||
@@ -80,6 +82,9 @@ const authOptions: AuthOptions = {
|
||||
// Ensure we can store user data in a database.
|
||||
adapter: PrismaAdapter(prisma),
|
||||
providers,
|
||||
session: {
|
||||
strategy: "jwt",
|
||||
},
|
||||
pages: {
|
||||
signIn: "/auth/signin",
|
||||
verifyRequest: "/auth/verify",
|
||||
@@ -94,6 +99,7 @@ const authOptions: AuthOptions = {
|
||||
session.user.role = token.role;
|
||||
session.user.isNew = token.isNew;
|
||||
session.user.name = token.name;
|
||||
session.user.tosAcceptanceDate = token.tosAcceptanceDate;
|
||||
return session;
|
||||
},
|
||||
/**
|
||||
@@ -101,13 +107,38 @@ const authOptions: AuthOptions = {
|
||||
* This let's use forward the role to the session object.
|
||||
*/
|
||||
async jwt({ token }) {
|
||||
const { isNew, name, role } = await prisma.user.findUnique({
|
||||
const { isNew, name, role, accounts, id } = await prisma.user.findUnique({
|
||||
where: { id: token.sub },
|
||||
select: { name: true, role: true, isNew: true },
|
||||
select: { name: true, role: true, isNew: true, accounts: true, id: true },
|
||||
});
|
||||
|
||||
const user: BackendUserCore = {
|
||||
id,
|
||||
display_name: name,
|
||||
auth_method: accounts.length > 0 ? accounts[0].provider : "local",
|
||||
};
|
||||
const oasstApiClient = createApiClientFromUser(user);
|
||||
|
||||
let tosAcceptanceDate = null;
|
||||
try {
|
||||
/**
|
||||
* when first creating a new user, the python backend is not informed about it
|
||||
* so this call will return a 404
|
||||
*
|
||||
* in the frontend, when the user accepts the tos, we do a full refresh
|
||||
* which means this function will be called again.
|
||||
*/
|
||||
tosAcceptanceDate = await oasstApiClient.fetch_tos_acceptance(user);
|
||||
} catch (err) {
|
||||
if (err.httpStatusCode !== 404) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
token.name = name;
|
||||
token.role = role;
|
||||
token.isNew = isNew;
|
||||
token.tosAcceptanceDate = tosAcceptanceDate;
|
||||
return token;
|
||||
},
|
||||
},
|
||||
@@ -150,9 +181,6 @@ const authOptions: AuthOptions = {
|
||||
}
|
||||
},
|
||||
},
|
||||
session: {
|
||||
strategy: "jwt",
|
||||
},
|
||||
};
|
||||
|
||||
export default function auth(req: NextApiRequest, res: NextApiResponse) {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { withoutRole } from "src/lib/auth";
|
||||
import { createApiClientFromUser } from "src/lib/oasst_client_factory";
|
||||
import { getBackendUserCore } from "src/lib/users";
|
||||
|
||||
const handler = withoutRole("banned", async (req, res, token) => {
|
||||
const user = await getBackendUserCore(token.sub);
|
||||
const oasstApiClient = createApiClientFromUser(user);
|
||||
if (req.method === "GET") {
|
||||
const tos_acceptance_date = await oasstApiClient.fetch_tos_acceptance(user);
|
||||
return res.status(200).json(tos_acceptance_date);
|
||||
} else if (req.method === "POST") {
|
||||
await oasstApiClient.set_tos_acceptance(user);
|
||||
return res.status(200).end();
|
||||
}
|
||||
|
||||
res.status(400).end();
|
||||
});
|
||||
|
||||
export default handler;
|
||||
@@ -8,10 +8,12 @@ import { get } from "src/lib/api";
|
||||
import { AvailableTasks, TaskCategory } from "src/types/Task";
|
||||
export { getDefaultStaticProps as getStaticProps } from "src/lib/default_static_props";
|
||||
import { TaskCategoryItem } from "src/components/Dashboard/TaskOption";
|
||||
import { ToSWrapper } from "src/components/ToSWrapper";
|
||||
import useSWR from "swr";
|
||||
|
||||
const Dashboard = () => {
|
||||
// Adding a demonstrative call to the backend that includes the web's JWT.
|
||||
// TODO: add CORS headers to the python backend
|
||||
useSWR(`${process.env.NEXT_PUBLIC_BACKEND_URL}/api/v1/auth/check`, get);
|
||||
|
||||
const {
|
||||
@@ -44,9 +46,11 @@ const Dashboard = () => {
|
||||
<meta name="description" content="Chat with Open Assistant and provide feedback." key="description" />
|
||||
</Head>
|
||||
<Flex direction="column" gap="10">
|
||||
<WelcomeCard />
|
||||
<TaskOption content={availableTaskTypes} />
|
||||
<LeaderboardWidget />
|
||||
<ToSWrapper>
|
||||
<WelcomeCard />
|
||||
<TaskOption content={availableTaskTypes} />
|
||||
<LeaderboardWidget />
|
||||
</ToSWrapper>
|
||||
</Flex>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -5,162 +5,174 @@ import { PolicyChapterCard } from "src/components/PolicyCards/PolicyChapterCard"
|
||||
import { PolicySectionCard } from "src/components/PolicyCards/PolicySectionCard";
|
||||
export { getDefaultStaticProps as getStaticProps } from "src/lib/default_static_props";
|
||||
|
||||
const TermsOfService = () => {
|
||||
const TermsData = [
|
||||
{
|
||||
number: "1",
|
||||
title: "Scope of Application, Amendments",
|
||||
desc: "",
|
||||
sections: [
|
||||
{
|
||||
number: "1.1",
|
||||
title: "",
|
||||
desc: `LAION (association in formation), Marie-Henning-Weg 143, 21035 Hamburg (hereinafter referred to as: "LAION") operates an online portal for the producing a machine learning model called Open Assistant using crowd-sourced data.`,
|
||||
},
|
||||
{
|
||||
number: "1.2",
|
||||
title: "",
|
||||
desc: "The present terms of use regulate the user relationship between the users of the portal and LAION.",
|
||||
},
|
||||
{
|
||||
number: "1.3",
|
||||
title: "",
|
||||
desc: "LAION reserves the right to amend these Terms of Use at any time, also with regard to persons already registered, if this becomes necessary due to changes in the law, changes in jurisdiction, changes in economic circumstances or gaps in these Terms of Use that subsequently become apparent. The user will be informed of such changes in good time by e-mail The user has the opportunity to object to the changes within 14 days of receipt of this e-mail. If the user does not object to the changes and continues to use the portal after expiry of the objection period, the changes shall be deemed to have been agreed effectively from the expiry of the period. If the user objects to the changes within the two-week period, LAION shall be entitled to exclude the user from using the portal. The user shall be informed of these effects once again in the e-mail.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
number: "2",
|
||||
title: "Subject of Use, Availability of the Service",
|
||||
desc: "",
|
||||
sections: [
|
||||
{
|
||||
number: "2.1",
|
||||
title: "",
|
||||
desc: "The portal serves as a platform for creating data to train an interactive agent for scientific purposes. All text and prompt generated through the service are used for scientific purposes, in particular for the optimization of the AI.",
|
||||
},
|
||||
{
|
||||
number: "2.2",
|
||||
title: "",
|
||||
desc: "The input of texts on the portal and the subsequent generation of text by the artificial intelligence provided by the portal do not give rise to any works protected by copyright. The user who has entered the text for the generation of the text shall have neither the exclusive rights of use nor any rights of an author to the generated text.",
|
||||
},
|
||||
{
|
||||
number: "2.3",
|
||||
title: "",
|
||||
desc: "LAION shall endeavour to ensure that the portal can be used as uninterruptedly as possible. However, there shall be no legal claim to the use of the portal. LAION reserves the right, at its own discretion, to change the portal at any time and without notice, to discontinue its operation or to exclude individual users from using it. Furthermore, it cannot be ruled out that temporary restrictions or interruptions may occur due to technical faults (such as interruption of the power supply, hardware and software errors, technical problems in the data lines).",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
number: "3",
|
||||
title: "User Obligations",
|
||||
desc: "",
|
||||
sections: [
|
||||
{
|
||||
number: "3.1",
|
||||
title: "",
|
||||
desc: "The user may only use the portal for the intended purposes. In particular, he/she may not misuse the portal. The user undertakes to refrain from generating text that violate criminal law, youth protection regulations or the applicable laws of the following countries: Federal Republic of Germany, United States of America (USA), Great Britain, user's place of residence. In particular it is prohibited to enter texts that lead to the creation of pornographic, violence-glorifying or paedosexual content and/or content that violates the personal rights of third parties. LAION reserves the right to file a criminal complaint with the competent authorities in the event of violations.",
|
||||
},
|
||||
{
|
||||
number: "3.2",
|
||||
title: "",
|
||||
desc: "The user undertakes not to use any programs, algorithms or other software in connection with the use of the portal which could interfere with the functioning of the portal. Furthermore, the user shall not take any measures that may result in an unreasonable or excessive load on the infrastructure of the portal or may interfere with it in a disruptive manner.",
|
||||
},
|
||||
{
|
||||
number: "3.3",
|
||||
title: "",
|
||||
desc: "If a user notices obvious errors in the portal which could lead to misuse of the portal or the contents contained therein, the user shall be obliged to report the error to LAION without delay.",
|
||||
},
|
||||
{
|
||||
number: "3.4",
|
||||
title: "",
|
||||
desc: "The use, distribution, storage, forwarding, editing and/or other use of images that violate these terms of use is prohibited.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
number: "4",
|
||||
title: "Liability",
|
||||
desc: "",
|
||||
sections: [
|
||||
{
|
||||
number: "4.1",
|
||||
title: "",
|
||||
desc: "LAION accepts no liability for the accuracy, completeness, reliability, up-to-dateness and usability of the content.",
|
||||
},
|
||||
{
|
||||
number: "4.2",
|
||||
title: "",
|
||||
desc: "LAION shall be liable without limitation for intent and gross negligence. In the case of simple negligence, LAION shall only be liable for damage resulting from injury to life, limb or health or an essential contractual obligation (obligation the fulfillment of which makes the proper performance of the contract possible in the first place and on the observance of which the contractual partner regularly trusts and may trust).",
|
||||
},
|
||||
{
|
||||
number: "4.3",
|
||||
title: "",
|
||||
desc: "In the event of a breach of material contractual obligations due to simple negligence, the liability of LAION shall be limited to the amount of the foreseeable, typically occurring damage. In all other respects liability shall be excluded.",
|
||||
},
|
||||
{
|
||||
number: "4.4",
|
||||
title: "",
|
||||
desc: "The above limitations of liability shall also apply in favour of the legal representatives and vicarious agents of LAION.",
|
||||
},
|
||||
{
|
||||
number: "4.5",
|
||||
title: "",
|
||||
desc: "LAION shall not be liable for the loss of data of the user. The user shall be solely responsible for the secure storage of his/her data.",
|
||||
},
|
||||
{
|
||||
number: "4.6",
|
||||
title: "",
|
||||
desc: "LAION shall not be liable for any damages incurred by the user as a result of the violation of these terms of use.",
|
||||
},
|
||||
{
|
||||
number: "4.7",
|
||||
title: "",
|
||||
desc: "LAION shall not be liable for the use of content generated on the portal by text input outside the portal. In particular, LAION shall not be liable for any damages incurred by the user due to the assumption of copyrights or exclusive rights of use.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
number: "5",
|
||||
title: "Data Protection",
|
||||
desc: "",
|
||||
sections: [
|
||||
{
|
||||
number: "5.1",
|
||||
title: "",
|
||||
desc: "LAION processes the personal data of users in accordance with the provisions of data protection law. Detailed information can be found in the privacy policy, available at: /privacy-policy.",
|
||||
},
|
||||
{
|
||||
number: "5.2",
|
||||
title: "",
|
||||
desc: "The user expressly agrees that communication within the scope of and for the purpose of the user relationship between him/her and LAION may also take place via unencrypted e-mails. The user is aware that unencrypted e-mails only offer limited security and confidentiality.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
number: "6",
|
||||
title: "Final Provisions",
|
||||
desc: "",
|
||||
sections: [
|
||||
{
|
||||
number: "6.1",
|
||||
title: "",
|
||||
desc: "The contractual relationship shall be governed exclusively by the law of the Federal Republic of Germany to the exclusion of the UN Convention on Contracts for the International Sale of Goods.",
|
||||
},
|
||||
{
|
||||
number: "6.2",
|
||||
title: "",
|
||||
desc: "Should individual provisions of these GTC including this provision be or become invalid in whole or in part, the validity of the remaining provisions shall remain unaffected. The invalid or missing provisions shall be replaced by the respective statutory provisions.",
|
||||
},
|
||||
{
|
||||
number: "6.3",
|
||||
title: "",
|
||||
desc: "If the customer is a merchant, a legal entity under public law or a special fund under public law, the place of jurisdiction for all disputes arising from and in connection with contracts concluded under these terms of use shall be the registered office of LAION.",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
const TermsData = [
|
||||
{
|
||||
number: "1",
|
||||
title: "Scope of Application, Amendments",
|
||||
desc: "",
|
||||
sections: [
|
||||
{
|
||||
number: "1.1",
|
||||
title: "",
|
||||
desc: `LAION (association in formation), Marie-Henning-Weg 143, 21035 Hamburg (hereinafter referred to as: "LAION") operates an online portal for the producing a machine learning model called Open Assistant using crowd-sourced data.`,
|
||||
},
|
||||
{
|
||||
number: "1.2",
|
||||
title: "",
|
||||
desc: "The present terms of use regulate the user relationship between the users of the portal and LAION.",
|
||||
},
|
||||
{
|
||||
number: "1.3",
|
||||
title: "",
|
||||
desc: "LAION reserves the right to amend these Terms of Use at any time, also with regard to persons already registered, if this becomes necessary due to changes in the law, changes in jurisdiction, changes in economic circumstances or gaps in these Terms of Use that subsequently become apparent. The user will be informed of such changes in good time by e-mail The user has the opportunity to object to the changes within 14 days of receipt of this e-mail. If the user does not object to the changes and continues to use the portal after expiry of the objection period, the changes shall be deemed to have been agreed effectively from the expiry of the period. If the user objects to the changes within the two-week period, LAION shall be entitled to exclude the user from using the portal. The user shall be informed of these effects once again in the e-mail.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
number: "2",
|
||||
title: "Subject of Use, Availability of the Service",
|
||||
desc: "",
|
||||
sections: [
|
||||
{
|
||||
number: "2.1",
|
||||
title: "",
|
||||
desc: "The portal serves as a platform for creating data to train an interactive agent for scientific purposes. All text and prompt generated through the service are used for scientific purposes, in particular for the optimization of the AI.",
|
||||
},
|
||||
{
|
||||
number: "2.2",
|
||||
title: "",
|
||||
desc: "The input of texts on the portal and the subsequent generation of text by the artificial intelligence provided by the portal do not give rise to any works protected by copyright. The user who has entered the text for the generation of the text shall have neither the exclusive rights of use nor any rights of an author to the generated text.",
|
||||
},
|
||||
{
|
||||
number: "2.3",
|
||||
title: "",
|
||||
desc: "LAION shall endeavour to ensure that the portal can be used as uninterruptedly as possible. However, there shall be no legal claim to the use of the portal. LAION reserves the right, at its own discretion, to change the portal at any time and without notice, to discontinue its operation or to exclude individual users from using it. Furthermore, it cannot be ruled out that temporary restrictions or interruptions may occur due to technical faults (such as interruption of the power supply, hardware and software errors, technical problems in the data lines).",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
number: "3",
|
||||
title: "User Obligations",
|
||||
desc: "",
|
||||
sections: [
|
||||
{
|
||||
number: "3.1",
|
||||
title: "",
|
||||
desc: "The user may only use the portal for the intended purposes. In particular, he/she may not misuse the portal. The user undertakes to refrain from generating text that violate criminal law, youth protection regulations or the applicable laws of the following countries: Federal Republic of Germany, United States of America (USA), Great Britain, user's place of residence. In particular it is prohibited to enter texts that lead to the creation of pornographic, violence-glorifying or paedosexual content and/or content that violates the personal rights of third parties. LAION reserves the right to file a criminal complaint with the competent authorities in the event of violations.",
|
||||
},
|
||||
{
|
||||
number: "3.2",
|
||||
title: "",
|
||||
desc: "The user undertakes not to use any programs, algorithms or other software in connection with the use of the portal which could interfere with the functioning of the portal. Furthermore, the user shall not take any measures that may result in an unreasonable or excessive load on the infrastructure of the portal or may interfere with it in a disruptive manner.",
|
||||
},
|
||||
{
|
||||
number: "3.3",
|
||||
title: "",
|
||||
desc: "If a user notices obvious errors in the portal which could lead to misuse of the portal or the contents contained therein, the user shall be obliged to report the error to LAION without delay.",
|
||||
},
|
||||
{
|
||||
number: "3.4",
|
||||
title: "",
|
||||
desc: "The use, distribution, storage, forwarding, editing and/or other use of images that violate these terms of use is prohibited.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
number: "4",
|
||||
title: "Liability",
|
||||
desc: "",
|
||||
sections: [
|
||||
{
|
||||
number: "4.1",
|
||||
title: "",
|
||||
desc: "LAION accepts no liability for the accuracy, completeness, reliability, up-to-dateness and usability of the content.",
|
||||
},
|
||||
{
|
||||
number: "4.2",
|
||||
title: "",
|
||||
desc: "LAION shall be liable without limitation for intent and gross negligence. In the case of simple negligence, LAION shall only be liable for damage resulting from injury to life, limb or health or an essential contractual obligation (obligation the fulfillment of which makes the proper performance of the contract possible in the first place and on the observance of which the contractual partner regularly trusts and may trust).",
|
||||
},
|
||||
{
|
||||
number: "4.3",
|
||||
title: "",
|
||||
desc: "In the event of a breach of material contractual obligations due to simple negligence, the liability of LAION shall be limited to the amount of the foreseeable, typically occurring damage. In all other respects liability shall be excluded.",
|
||||
},
|
||||
{
|
||||
number: "4.4",
|
||||
title: "",
|
||||
desc: "The above limitations of liability shall also apply in favour of the legal representatives and vicarious agents of LAION.",
|
||||
},
|
||||
{
|
||||
number: "4.5",
|
||||
title: "",
|
||||
desc: "LAION shall not be liable for the loss of data of the user. The user shall be solely responsible for the secure storage of his/her data.",
|
||||
},
|
||||
{
|
||||
number: "4.6",
|
||||
title: "",
|
||||
desc: "LAION shall not be liable for any damages incurred by the user as a result of the violation of these terms of use.",
|
||||
},
|
||||
{
|
||||
number: "4.7",
|
||||
title: "",
|
||||
desc: "LAION shall not be liable for the use of content generated on the portal by text input outside the portal. In particular, LAION shall not be liable for any damages incurred by the user due to the assumption of copyrights or exclusive rights of use.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
number: "5",
|
||||
title: "Data Protection",
|
||||
desc: "",
|
||||
sections: [
|
||||
{
|
||||
number: "5.1",
|
||||
title: "",
|
||||
desc: "LAION processes the personal data of users in accordance with the provisions of data protection law. Detailed information can be found in the privacy policy, available at: /privacy-policy.",
|
||||
},
|
||||
{
|
||||
number: "5.2",
|
||||
title: "",
|
||||
desc: "The user expressly agrees that communication within the scope of and for the purpose of the user relationship between him/her and LAION may also take place via unencrypted e-mails. The user is aware that unencrypted e-mails only offer limited security and confidentiality.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
number: "6",
|
||||
title: "Final Provisions",
|
||||
desc: "",
|
||||
sections: [
|
||||
{
|
||||
number: "6.1",
|
||||
title: "",
|
||||
desc: "The contractual relationship shall be governed exclusively by the law of the Federal Republic of Germany to the exclusion of the UN Convention on Contracts for the International Sale of Goods.",
|
||||
},
|
||||
{
|
||||
number: "6.2",
|
||||
title: "",
|
||||
desc: "Should individual provisions of these GTC including this provision be or become invalid in whole or in part, the validity of the remaining provisions shall remain unaffected. The invalid or missing provisions shall be replaced by the respective statutory provisions.",
|
||||
},
|
||||
{
|
||||
number: "6.3",
|
||||
title: "",
|
||||
desc: "If the customer is a merchant, a legal entity under public law or a special fund under public law, the place of jurisdiction for all disputes arising from and in connection with contracts concluded under these terms of use shall be the registered office of LAION.",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const TermsOfService = () => (
|
||||
<Stack spacing="8">
|
||||
{TermsData.map((chapter, chapterIndex) => (
|
||||
<PolicyChapterCard key={chapterIndex} chapter={chapter}>
|
||||
{chapter.sections && chapter.sections.length
|
||||
? chapter.sections.map((section, sectionIndex) => <PolicySectionCard key={sectionIndex} section={section} />)
|
||||
: ""}
|
||||
</PolicyChapterCard>
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
|
||||
const TermsOfServicePage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
@@ -171,23 +183,12 @@ const TermsOfService = () => {
|
||||
<Heading as="h1" size="xl" color="blue.500" mb="6">
|
||||
Terms of Service
|
||||
</Heading>
|
||||
|
||||
<Stack spacing="8">
|
||||
{TermsData.map((chapter, chapterIndex) => (
|
||||
<PolicyChapterCard key={chapterIndex} chapter={chapter}>
|
||||
{chapter.sections && chapter.sections.length
|
||||
? chapter.sections.map((section, sectionIndex) => (
|
||||
<PolicySectionCard key={sectionIndex} section={section} />
|
||||
))
|
||||
: ""}
|
||||
</PolicyChapterCard>
|
||||
))}
|
||||
</Stack>
|
||||
<TermsOfService />
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
TermsOfService.getLayout = getTransparentHeaderLayout;
|
||||
TermsOfServicePage.getLayout = getTransparentHeaderLayout;
|
||||
|
||||
export default TermsOfService;
|
||||
export default TermsOfServicePage;
|
||||
|
||||
@@ -40,6 +40,36 @@ export interface BackendUser extends BackendUserCore {
|
||||
* True when the user is marked for deletion. False otherwise.
|
||||
*/
|
||||
deleted: boolean;
|
||||
|
||||
/**
|
||||
* time the user was created
|
||||
*/
|
||||
created_date: string; // iso date string
|
||||
|
||||
/**
|
||||
* if the user is shown on leaderboards
|
||||
*/
|
||||
show_on_leaderboard: boolean;
|
||||
|
||||
/**
|
||||
* streak
|
||||
*/
|
||||
streak_days: unknown;
|
||||
|
||||
/**
|
||||
* last day of latest streak
|
||||
*/
|
||||
streak_last_day_date: string | null; // iso date string
|
||||
|
||||
/**
|
||||
* last time this use made an interaction with the backend
|
||||
*/
|
||||
last_activity_date: string | null; // iso date string
|
||||
|
||||
/**
|
||||
* the date when the user accepted terms of the service
|
||||
*/
|
||||
tos_acceptance_date: string | null; // iso date string
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Vendored
+4
-2
@@ -1,11 +1,12 @@
|
||||
import type common from "public/locales/en/common.json";
|
||||
import type dashboard from "public/locales/en/dashboard.json";
|
||||
import type index from "public/locales/en/index.json";
|
||||
import type labelling from "public/locales/en/labelling.json";
|
||||
import type leaderboard from "public/locales/en/leaderboard.json";
|
||||
import type message from "public/locales/en/message.json";
|
||||
import type labelling from "public/locales/en/labelling.json";
|
||||
import type tasks from "public/locales/en/tasks.json";
|
||||
import type side_menu from "public/locales/en/side_menu.json";
|
||||
import type tasks from "public/locales/en/tasks.json";
|
||||
import type tos from "public/locales/en/tos.json";
|
||||
|
||||
declare module "i18next" {
|
||||
interface CustomTypeOptions {
|
||||
@@ -18,6 +19,7 @@ declare module "i18next" {
|
||||
message: typeof message;
|
||||
labelling: typeof labelling;
|
||||
side_menu: typeof side_menu;
|
||||
tos: typeof tos;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+4
@@ -8,6 +8,8 @@ declare module "next-auth" {
|
||||
role: string;
|
||||
/** True when the user is new. */
|
||||
isNew: boolean;
|
||||
/** Iso timestamp of the user's acceptance of the terms of service */
|
||||
tosAcceptanceDate?: string;
|
||||
} & DefaultSession["user"];
|
||||
}
|
||||
}
|
||||
@@ -18,5 +20,7 @@ declare module "next-auth/jwt" {
|
||||
role?: string;
|
||||
/** True when the user is new. */
|
||||
isNew?: boolean;
|
||||
/** Iso timestamp of the user's acceptance of the terms of service */
|
||||
tosAcceptanceDate?: string;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user