diff --git a/.aws/config b/.aws/config new file mode 100644 index 00000000..ee8f7ce7 --- /dev/null +++ b/.aws/config @@ -0,0 +1,3 @@ +[default] +region = us-east-1 +output = json diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml new file mode 100644 index 00000000..d5281efe --- /dev/null +++ b/.github/workflows/pull_request.yml @@ -0,0 +1,29 @@ +on: + pull_request: + +env: + NODE_VERSION: "20.x" + +permissions: + contents: read + +jobs: + test-build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4.1.1 + with: + fetch-depth: "0" + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + cache: "npm" + + - name: Build to make sure data is OK + run: | + # Set up yarn + yarn install + # Build + yarn build:public diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml new file mode 100644 index 00000000..695f7456 --- /dev/null +++ b/.github/workflows/push.yml @@ -0,0 +1,72 @@ +on: + push: + branches: ["main", "staging"] + workflow_dispatch: + +# Cancel in-progress jobs or runs for the current workflow +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + NODE_VERSION: "20.x" + +permissions: + contents: read + +jobs: + pre-build: + runs-on: ubuntu-latest + outputs: + env_name: ${{ steps.set_env.outputs.env_name }} + steps: + - name: Set environment name + id: set_env + run: | + if [[ "${{ github.ref_name }}" == "staging" ]]; then + echo "env_name=Development" >> $GITHUB_OUTPUT + fi + build: + needs: [pre-build] + runs-on: ubuntu-latest + environment: + name: ${{ needs.pre-build.outputs.env_name }} + steps: + - uses: actions/checkout@v4.1.1 + with: + fetch-depth: "0" + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + cache: "npm" + + - name: Build and deploy + run: | + # Set up the environment variables + export NODE_OPTIONS=--experimental-wasm-modules + export AUTH_SECRET=${{ secrets.AUTH_SECRET }} + export AUTH0_CLIENT_ID=${{ secrets.AUTH0_CLIENT_ID }} + export AUTH0_CLIENT_SECRET=${{ secrets.AUTH0_CLIENT_SECRET }} + export AUTH_TRUST_HOST=${{ vars.AUTH_TRUST_HOST }} + export AUTH0_ISSUER_BASE=${{ vars.AUTH0_ISSUER_BASE }} + export AUTH_API_URL=${{ vars.AUTH_API_URL }} + export SPIRE_WEBSITES_ID=${{ vars.SPIRE_WEBSITES_ID }} + export PUBLIC_KEY_URL=${{ vars.PUBLIC_KEY_URL }} + export CUSTOM_DOMAIN=${{ vars.CUSTOM_DOMAIN }} + # Set up yarn + yarn install + # Set up AWS CLI & credentials + sudo apt update && sudo apt upgrade -y && sudo apt install -y pipx + curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" + unzip awscliv2.zip + sudo ./aws/install --update + cp -R .aws ~/ + pipx run pipenv install + $(pipx run pipenv run python ./get_aws_creds.py -i ${{ secrets.VAULT_ROLE_ID }} -s ${{ secrets.VAULT_SECRET_ID }} -r ${{ secrets.VAULT_ROLE }}) + # Build & deploy + if [[ "${{ github.ref_name }}" == "staging" ]]; then + export STAGE="dev" + fi + yarn sst deploy --stage $STAGE diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..4b787aeb --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +# build output +dist/ +dist_pagefind/ +dist_prebuild/ + +# generated types +.astro/ +cache/ + +# dependencies +node_modules/ +.yarn/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + + +# environment variables +.env +.env.* + +# macOS-specific files +.DS_Store + +# sst +.sst diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..59acb2af --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +ignore-scripts=false \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..22a15055 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + "recommendations": ["astro-build.astro-vscode"], + "unwantedRecommendations": [] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..d6422097 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "command": "./node_modules/.bin/astro dev", + "name": "Development server", + "request": "launch", + "type": "node-terminal" + } + ] +} diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 00000000..6aa46049 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,10 @@ +.github/workflows @pcolmer @louismorgan-linaro @DelaraGi +CODEOWNERS @pcolmer @louismorgan-linaro @DelaraGi +.gitignore @pcolmer @louismorgan-linaro @DelaraGi +package.json @pcolmer @louismorgan-linaro @DelaraGi +src/components @pcolmer @louismorgan-linaro @DelaraGi +src/layouts @pcolmer @louismorgan-linaro @DelaraGi +src/pages @pcolmer @louismorgan-linaro @DelaraGi +src/styles @pcolmer @louismorgan-linaro @DelaraGi +src/util @pcolmer @louismorgan-linaro @DelaraGi +src/content/config.ts @pcolmer @louismorgan-linaro @DelaraGi diff --git a/Pipfile b/Pipfile new file mode 100644 index 00000000..a799d5dd --- /dev/null +++ b/Pipfile @@ -0,0 +1,12 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +requests = "*" + +[dev-packages] + +[requires] +python_version = "3" diff --git a/README.md b/README.md new file mode 100644 index 00000000..315f86e2 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# "Works on Windows on Arm" website git repository + +This repository is used to build `staging.worksonwoa.com` and, from there, `www.worksonwoa.com`. + +The websites are built automatically when the staging and main branches are updated, as appropriate. + +The staging branch is updated by: + +- Forking this repository +- Making the changes you want to make +- Raising a pull request against the staging branch +- Waiting for a repository maintainer to review and approve your changes + +Once the pull request is approved, your changes will be merged to the staging branch and published to staging.worksonwoa.com. + +A repository maintainer can then merge all changes from staging to main in order to cause the main website to be updated and rebuilt. + +## Contributing + +Details of the schemas used in the game and user report files can be found by reading https://www.worksonwoa.com/contributing + +## Questions? + +If you have any questions about updating or building this website, please contact Linaro IT Support at [it-support@linaro.org](mailto:it-support@linaro.org). + +## Developer Info + +Running the site locally will require `Node.js` and the `yarn` package manager. + +Install dependencies with `yarn install` then, to run the site locally, run `yarn start:build`. Press CTRL+C to stop the local web server when you have finished. diff --git a/astro.config.mjs b/astro.config.mjs new file mode 100644 index 00000000..fb4f8a1e --- /dev/null +++ b/astro.config.mjs @@ -0,0 +1,68 @@ +import { defineConfig } from "astro/config"; +import aws from "astro-sst"; +import sitemap from "@astrojs/sitemap"; +import tailwind from "@astrojs/tailwind"; +import solidJs from "@astrojs/solid-js"; +import pagefind from "./integrations/pagefind"; +import auth from "./integrations/auth"; +import { loadEnv } from "vite"; + + +const { IS_PUBLIC, PRE_BUILD, CUSTOM_DOMAIN } = loadEnv( + process.env.NODE_ENV, + process.cwd(), + "" +); +const is_public = IS_PUBLIC === "true" +const is_pre_build = PRE_BUILD === "true" + +// https://astro.build/config +export default defineConfig({ + ...(is_public + ? { + output: "static", + integrations: [ + sitemap(), + pagefind({ + is_pre_build: is_pre_build, + is_public: is_public, + }), + tailwind({ + applyBaseStyles: false, + }), + solidJs(), + ], + } + : { + output: PRE_BUILD ? "hybrid" : "server", + adapter: aws({ + serverRoutes: ["/api/*"], + }), + integrations: [ + sitemap(), + pagefind({ + is_pre_build: is_pre_build, + is_public: is_public, + }), + tailwind({ + applyBaseStyles: false, + }), + solidJs(), + auth({ + injectEndpoints: true, + }), + ], + }), + site: `https://${CUSTOM_DOMAIN}`, + cacheDir: "./cache", + compressHTML: true, + build: { + rollupOptions: { + external: ["/pagefind/pagefind.js"], + }, + redirects: false, + }, + vite: { + optimizeDeps: { exclude: ['auth:config'] }, + } +}); diff --git a/auth.config.ts b/auth.config.ts new file mode 100644 index 00000000..199d37f6 --- /dev/null +++ b/auth.config.ts @@ -0,0 +1,157 @@ +// auth.config.ts +import { defineConfig } from "auth-astro"; +import { + verifyBiscuitUser, + parseBiscuitMetadata, + type Bwks, +} from "./src/lib/auth"; + +const { + AUTH0_CLIENT_ID, + AUTH0_CLIENT_SECRET, + AUTH0_ISSUER_BASE, + AUTH_API_URL, + SPIRE_WEBSITES_ID, + PUBLIC_KEY_URL, +} = import.meta.env; + +const isDev = import.meta.env.DEV; +const WEBSITE_URL = import.meta.env.SITE; + +function getPublicKeys() { + return fetch(`${PUBLIC_KEY_URL}`, { + cache: "no-store", + }); +} + +async function afterToken(accessToken: string) { + // fetch biscuit public keys + const res = await getPublicKeys(); + const public_keys = await res.json(); + + if (!res.ok || !public_keys) { + console.error(public_keys); + throw new Error("failed to fetch public keys"); + } + + // verify biscuit and extract metadata + const auth = verifyBiscuitUser(accessToken, public_keys, SPIRE_WEBSITES_ID); + + const metadata = parseBiscuitMetadata(auth); + if (!metadata) { + throw new Error("error extracting biscuit metadata"); + } + + const [id, first_name, surname] = metadata; + + return { + profile: { + id, + first_name, + surname, + }, + public_keys, + }; +} + +export default defineConfig({ + providers: [ + { + id: "spire", + name: "spire", + type: "oidc", + clientId: AUTH0_CLIENT_ID, + clientSecret: AUTH0_CLIENT_SECRET, + checks: ["pkce", "state"], + authorization: { + url: `${AUTH_API_URL}/oauth/authorize`, + params: { + scope: "openid email offline_access profile", + client_id: AUTH0_CLIENT_ID, + response_type: "code", + }, + }, + issuer: AUTH0_ISSUER_BASE, + jwks_endpoint: AUTH0_ISSUER_BASE + ".well-known/jwks.json", + client: { + token_endpoint_auth_method: "client_secret_post", + }, + token: { + url: `${AUTH_API_URL}/oauth/token`, + params: { + scope: "openid email offline_access profile", + response_type: "code", + client_id: AUTH0_CLIENT_ID, + }, + httpOptions: { + timeout: 30000, + }, + }, + profile: (profile: any) => { + return { + id: profile.sub, + ...profile, + }; + }, + }, + ], + callbacks: { + async session({ session, token }: any) { + session.profile = token.profile; + session.access_token = token.access_token; + session.public_keys = token.public_keys; + session.expires_at = token.expires_at; + return session; + }, + async jwt({ account, token }) { + // this is only run after sign in + if (account) { + try { + const { profile, public_keys } = await afterToken( + account.access_token! + ); + return { + access_token: account.access_token, + // refresh_token: account.refresh_token, + expires_at: account.expires_at, + public_keys, + profile, + }; + } catch (error) { + console.error(error); + throw new Error("AccessDenied"); + } + } + + // if not sign in and token is valid, return as is + return token; + }, + }, + pages: { + signIn: "/auth/signin", + error: "/auth/error", + }, +}); + +declare module "@auth/core" { + /** + * Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context + */ + interface Session { + profile: any; + } +} +declare module "@auth/core" { + interface JWT { + access_token: string; + expires_at: number; + // refresh_token: string; + public_keys: Bwks[]; + profile: { + id: string; + first_name: string; + surname: string; + }; + error?: "RefreshAccessTokenError" | "BiscuitPublicKeysError"; + } +} diff --git a/cdk.context.json b/cdk.context.json new file mode 100644 index 00000000..db3ff612 --- /dev/null +++ b/cdk.context.json @@ -0,0 +1,10 @@ +{ + "hosted-zone:account=497503705704:domainName=staging.worksonwoa.com:region=us-east-1": { + "Id": "/hostedzone/Z03672012HG3S9ZFMNF15", + "Name": "staging.worksonwoa.com." + }, + "hosted-zone:account=497503705704:domainName=worksonwoa.com:region=us-east-1": { + "Id": "/hostedzone/Z08678803D3DH2PWQL6O9", + "Name": "worksonwoa.com." + } +} diff --git a/get_aws_creds.py b/get_aws_creds.py new file mode 100755 index 00000000..08a6b30b --- /dev/null +++ b/get_aws_creds.py @@ -0,0 +1,89 @@ +#!/usr/bin/python3 +# +# For a given profile name, role ID, secret ID and role, set the two AWS +# environment variables to the secret values. + + +import sys +import getopt +import requests + + +def vault_login(role_id, secret_id, aws_role): + access_key = None + secret_key = None + security_token = None + # Since this code doesn't run on an EC2 instance, we use the AppRole + # authentication method. + data = { + "role_id": role_id, + "secret_id": secret_id + } + r = requests.post( + "https://login.linaro.org:8200/v1/auth/approle/login", + json=data + ) + # That gets us the vault token. Now get the credentials for the specified + # profile/account name. + header = { + "X-Vault-Token": r.json()["auth"]["client_token"] + } + r = requests.post( + "https://login.linaro.org:8200/v1/aws/sts/%s" % aws_role, + headers=header + ) + if r.status_code == 200: + result = r.json() + access_key = result["data"]["access_key"] + secret_key = result["data"]["secret_key"] + security_token = result["data"]["security_token"] + # Now revoke the client token + requests.post( + "https://login.linaro.org:8200/v1/auth/token/revoke-self", + headers=header) + return access_key, secret_key, security_token + +def main(argv): + role_id = None + secret_id = None + aws_role = None + try: + opts, args = getopt.getopt(argv, "i:s:r:") + except Exception: + print( + "get_aws_creds.py" + " -i " + " -s " + " -r ") + sys.exit(1) + for opt, arg in opts: + if opt == "-i": + role_id = arg + if opt == "-s": + secret_id = arg + if opt == "-r": + aws_role = arg + if (role_id is None or + secret_id is None or + aws_role is None): + print( + "get_aws_creds.py" + " -i " + " -s " + " -r ") + sys.exit(1) + access, secret, token = vault_login( + role_id, + secret_id, + aws_role + ) + if access is None: + print("Failed to authenticate or invalid role specified") + sys.exit(1) + print("export AWS_ACCESS_KEY_ID=%s" % access) + print("export AWS_SECRET_ACCESS_KEY=%s" % secret) + print("export AWS_SESSION_TOKEN=%s" % token) + + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/integrations/auth.ts b/integrations/auth.ts new file mode 100644 index 00000000..7449c16c --- /dev/null +++ b/integrations/auth.ts @@ -0,0 +1,69 @@ +import type { AstroIntegration } from 'astro' +import { virtualConfigModule, type AstroAuthConfig } from 'auth-astro/src/config' + + +export default (config: AstroAuthConfig = {}): AstroIntegration => ({ + name: 'astro-auth', + hooks: { + 'astro:config:setup': async ({ + config: astroConfig, + injectRoute, + injectScript, + updateConfig, + addMiddleware, + logger, + }) => { + if (astroConfig.output === 'static') + throw new Error( + 'auth-astro requires server-side rendering. Please set output to "server" & install an adapter. See https://docs.astro.build/en/guides/deploy/#adding-an-adapter-for-ssr' + ) + + updateConfig({ + vite: { + plugins: [virtualConfigModule(config.configFile) as any], + optimizeDeps: { exclude: ['auth:config'] }, + }, + }) + + config.prefix ??= '/api/auth' + + if (config.injectEndpoints !== false) { + injectRoute({ + pattern: '/api/[...auth]', + entrypoint: './src/auth_routes/api/[...auth].js', + + }); + + ["access-denied", "error", "index", "signin", "signout"].forEach((route: string) => { + injectRoute({ + pattern: `/auth/${route == "index" ? "" : route}`, + entrypoint: `./src/auth_routes/auth/${route}.astro`, + }) + }) + addMiddleware({ + entrypoint: process.cwd() + '/src/auth_routes/middleware', + order: 'pre' + }); + } + + if (!astroConfig.adapter) { + logger.error('No Adapter found, please make sure you provide one in your Astro config') + } + const edge = false + + if ( + (!edge && globalThis.process && process.versions.node < '19.0.0') || + (process.env.NODE_ENV === 'development' && edge) + ) { + injectScript( + 'page-ssr', + `import crypto from "node:crypto"; +if (!globalThis.crypto) globalThis.crypto = crypto; +if (typeof globalThis.crypto.subtle === "undefined") globalThis.crypto.subtle = crypto.webcrypto.subtle; +if (typeof globalThis.crypto.randomUUID === "undefined") globalThis.crypto.randomUUID = crypto.randomUUID; +` + ) + } + }, + }, +}) \ No newline at end of file diff --git a/integrations/pagefind.ts b/integrations/pagefind.ts new file mode 100644 index 00000000..d7a97bf7 --- /dev/null +++ b/integrations/pagefind.ts @@ -0,0 +1,57 @@ +import type { AstroIntegration } from "astro"; +import { execSync } from "child_process"; +import sirv from "sirv"; + +export default function pagefind({ + is_pre_build, + is_public, +}: { + is_pre_build: boolean; + is_public: boolean; +}): AstroIntegration { + let outDir: string; + if (is_pre_build) return { name: "pagefind", hooks: {} }; + return { + name: "pagefind", + hooks: { + "astro:config:setup": ({ config, logger }) => { + outDir = is_public ? "./dist" : "./dist_prebuild/dist/client"; + }, + "astro:server:setup": ({ server, logger }) => { + if (!outDir) { + logger.warn( + "astro-pagefind couldn't reliably determine the output directory. Search assets will not be served." + ); + return; + } + logger.warn(outDir); + const serve = sirv(outDir, { + dev: true, + etag: true, + }); + server.middlewares.use((req, res, next) => { + if (req.url?.startsWith("/pagefind/")) { + serve(req, res, next); + } else { + next(); + } + }); + }, + "astro:build:done": ({ logger }) => { + logger.warn(outDir); + + if (!outDir) { + logger.warn( + "astro-pagefind couldn't reliably determine the output directory. Search index will not be built." + ); + return; + } + + const cmd = `npx pagefind --site "${outDir}"`; + execSync(cmd, { + stdio: [process.stdin, process.stdout, process.stderr], + }); + }, + }, + }; +} diff --git a/old workflows/push.yml b/old workflows/push.yml new file mode 100644 index 00000000..4ebb729e --- /dev/null +++ b/old workflows/push.yml @@ -0,0 +1,81 @@ +on: + push: + branches: ["main", "staging"] + workflow_dispatch: + +# Cancel in-progress jobs or runs for the current workflow +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + NODE_VERSION: "18.x" + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: "0" + - name: Set up environment + run: | + if [[ $GITHUB_REF == 'refs/heads/main' ]]; then + echo "No support for main branch yet" + else + echo "CF_DIST_ID_STATIC_LO=${{ vars.STAGING_CF_DIST }}" >> "$GITHUB_ENV" + echo "AWS_STATIC_SITE_URL=${{ vars.STAGING_SITE_URL }}" >> "$GITHUB_ENV" + echo "CF_DIST_ID_STATIC_LO=${{ vars.STAGING_CF_DIST }}" + echo "AWS_STATIC_SITE_URL=${{ vars.STAGING_SITE_URL }}" + fi + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_VERSION }} + cache: "npm" + + - name: npm install, build, and test + run: | + npm install + npm run build --if-present + npm run test --if-present + + - name: Deploy to AWS + run: | + sudo apt update && sudo apt upgrade -y && sudo apt install -y pipx + curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" + unzip awscliv2.zip + sudo ./aws/install --update + cp -R .aws ~/ + pipx run pipenv install + $(pipx run pipenv run python ./get_aws_creds.py -i ${{ secrets.VAULT_ROLE_ID }} -s ${{ secrets.VAULT_SECRET_ID }} -r ${{ secrets.VAULT_ROLE }}) + cd dist + echo "aws s3 sync --exclude \"*\" --include \"*.html\" --cache-control \"no-cache, max-age=86400\" ./ \"s3://$AWS_STATIC_SITE_URL\" --delete --no-progress" + /usr/local/bin/aws s3 sync --exclude "*" --include "*.html" --cache-control "no-cache, max-age=86400" ./ "s3://$AWS_STATIC_SITE_URL" --delete --no-progress + echo "aws s3 sync --include \"*\" --exclude \"*.html\" --cache-control \"public, max-age=86400\" ./ \"s3://$AWS_STATIC_SITE_URL\" --delete --no-progress" + /usr/local/bin/aws s3 sync --include "*" --exclude "*.html" --cache-control "public, max-age=86400" ./ "s3://$AWS_STATIC_SITE_URL" --delete --no-progress + cd .. + echo "======== CREATING INVALIDATION ========" + invID=$(aws cloudfront create-invalidation \ + --distribution-id "$CF_DIST_ID_STATIC_LO" --paths "/*" --query Invalidation.Id --output text) + export invID + echo "======== INVALIDATION ID ========" + echo "${invID}" + echo "======== POLLING COMPLETED INVALIDATION ========" + until aws cloudfront wait invalidation-completed \ + --distribution-id "$CF_DIST_ID_STATIC_LO" --id "${invID}" 2>/dev/null + do + # Still waiting - output some progress + echo "Still waiting ..." + aws cloudfront get-invalidation \ + --distribution-id "$CF_DIST_ID_STATIC_LO" --id "${invID}" + sleep 10 + done + # and final confirmation + aws cloudfront get-invalidation \ + --distribution-id "$CF_DIST_ID_STATIC_LO" --id "${invID}" + echo "======== INVALIDATION COMPLETED ========" diff --git a/package.json b/package.json new file mode 100644 index 00000000..569970cc --- /dev/null +++ b/package.json @@ -0,0 +1,54 @@ +{ + "name": "windows-on-arm", + "license": "MIT", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "sst bind astro dev", + "preview": "astro preview", + "postbuild": "pagefind --site ./dist_prebuild/dist/client --output-path ./dist/client/pagefind", + "start": "astro dev", + "start:public": "IS_PUBLIC=true astro dev", + "start:build": "IS_PUBLIC=true astro build --ignore-scripts && IS_PUBLIC=true astro dev", + "prebuild": "PRE_BUILD=true astro build --outDir ./dist_prebuild/", + "build": "astro build", + "build:public": "IS_PUBLIC=true astro build --ignore-scripts", + "astro": "astro", + "sst:deploy": "sst deploy", + "sst:dev": "sst dev" + }, + "dependencies": { + "@astrojs/check": "0.5.6", + "@astrojs/mdx": "2.1.1", + "@astrojs/node": "^8.2.1", + "@astrojs/rss": "4.0.5", + "@astrojs/sitemap": "3.1.1", + "@astrojs/solid-js": "4.0.1", + "@astrojs/tailwind": "5.1.0", + "@astrolib/seo": "^0.6.0", + "@auth/core": "^0.18.6", + "@biscuit-auth/biscuit-wasm": "^0.4.0", + "@solid-primitives/pagination": "^0.2.8", + "astro": "4.4.5", + "astro-pagefind": "^1.4.0", + "astro-sst": "^2.40.3", + "auth-astro": "^4.1.1", + "dayjs": "^1.11.10", + "sass": "^1.63.6", + "set-cookie-parser": "^2.6.0", + "solid-icons": "^1.1.0", + "solid-js": "^1.4.3", + "tailwindcss": "^3.0.24", + "typescript": "^5.2.2" + }, + "devDependencies": { + "@tailwindcss/typography": "^0.5.12", + "astro-sst": "^2.40.3", + "aws-cdk-lib": "2.124.0", + "constructs": "10.3.0", + "pagefind": "^1.1.0", + "sst": "^2.40.3", + "vite": "^4.4.11", + "write-yaml-file": "^5.0.0" + } +} diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png new file mode 100644 index 00000000..9c94e7f2 Binary files /dev/null and b/public/android-chrome-192x192.png differ diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png new file mode 100644 index 00000000..56c3f71b Binary files /dev/null and b/public/android-chrome-512x512.png differ diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 00000000..a7ca8404 Binary files /dev/null and b/public/apple-touch-icon.png differ diff --git a/public/browserconfig.xml b/public/browserconfig.xml new file mode 100644 index 00000000..b3930d0f --- /dev/null +++ b/public/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #da532c + + + diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png new file mode 100644 index 00000000..4f223e90 Binary files /dev/null and b/public/favicon-16x16.png differ diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png new file mode 100644 index 00000000..705d3415 Binary files /dev/null and b/public/favicon-32x32.png differ diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 00000000..51123b91 Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/icons/123PhotoViewer.svg b/public/icons/123PhotoViewer.svg new file mode 100644 index 00000000..3c7fb268 --- /dev/null +++ b/public/icons/123PhotoViewer.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/public/icons/4kVideoDownloaderPlus.svg b/public/icons/4kVideoDownloaderPlus.svg new file mode 100644 index 00000000..f06a107f --- /dev/null +++ b/public/icons/4kVideoDownloaderPlus.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/public/icons/5KPlayer.svg b/public/icons/5KPlayer.svg new file mode 100644 index 00000000..46400885 --- /dev/null +++ b/public/icons/5KPlayer.svg @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/icons/7zip.svg b/public/icons/7zip.svg new file mode 100644 index 00000000..48040304 --- /dev/null +++ b/public/icons/7zip.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/icons/8zip.svg b/public/icons/8zip.svg new file mode 100644 index 00000000..2cd96bbb --- /dev/null +++ b/public/icons/8zip.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/public/icons/BlueStacks.png b/public/icons/BlueStacks.png new file mode 100644 index 00000000..b0cfe6e2 Binary files /dev/null and b/public/icons/BlueStacks.png differ diff --git a/public/icons/GoogleChrome.svg b/public/icons/GoogleChrome.svg new file mode 100644 index 00000000..c34b12c1 --- /dev/null +++ b/public/icons/GoogleChrome.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/Microsoft3DBuilder.png b/public/icons/Microsoft3DBuilder.png new file mode 100644 index 00000000..24076b5b Binary files /dev/null and b/public/icons/Microsoft3DBuilder.png differ diff --git a/public/icons/Microsoft3DViewer.png b/public/icons/Microsoft3DViewer.png new file mode 100644 index 00000000..d10c7a2a Binary files /dev/null and b/public/icons/Microsoft3DViewer.png differ diff --git a/public/icons/MicrosoftAccess.png b/public/icons/MicrosoftAccess.png new file mode 100644 index 00000000..1396621a Binary files /dev/null and b/public/icons/MicrosoftAccess.png differ diff --git a/public/icons/MicrosoftAlarmAndClock.png b/public/icons/MicrosoftAlarmAndClock.png new file mode 100644 index 00000000..a8276791 Binary files /dev/null and b/public/icons/MicrosoftAlarmAndClock.png differ diff --git a/public/icons/MicrosoftAzureVirtualDesktopPreview.png b/public/icons/MicrosoftAzureVirtualDesktopPreview.png new file mode 100644 index 00000000..a11d2230 Binary files /dev/null and b/public/icons/MicrosoftAzureVirtualDesktopPreview.png differ diff --git a/public/icons/MicrosoftBitlocker.png b/public/icons/MicrosoftBitlocker.png new file mode 100644 index 00000000..d4f3f4f2 Binary files /dev/null and b/public/icons/MicrosoftBitlocker.png differ diff --git a/public/icons/MicrosoftCalculator.png b/public/icons/MicrosoftCalculator.png new file mode 100644 index 00000000..d38ddddf Binary files /dev/null and b/public/icons/MicrosoftCalculator.png differ diff --git a/public/icons/MicrosoftCamera.png b/public/icons/MicrosoftCamera.png new file mode 100644 index 00000000..e0563275 Binary files /dev/null and b/public/icons/MicrosoftCamera.png differ diff --git a/public/icons/MicrosoftClipChamp.png b/public/icons/MicrosoftClipChamp.png new file mode 100644 index 00000000..2b466cf2 Binary files /dev/null and b/public/icons/MicrosoftClipChamp.png differ diff --git a/public/icons/MicrosoftDefender.png b/public/icons/MicrosoftDefender.png new file mode 100644 index 00000000..d3be7eb6 Binary files /dev/null and b/public/icons/MicrosoftDefender.png differ diff --git a/public/icons/MicrosoftDeviceGuard.webp b/public/icons/MicrosoftDeviceGuard.webp new file mode 100644 index 00000000..163870a5 Binary files /dev/null and b/public/icons/MicrosoftDeviceGuard.webp differ diff --git a/public/icons/MicrosoftEdge.svg b/public/icons/MicrosoftEdge.svg new file mode 100644 index 00000000..4f95f8de --- /dev/null +++ b/public/icons/MicrosoftEdge.svg @@ -0,0 +1 @@ + diff --git a/public/icons/MicrosoftExcel.avif b/public/icons/MicrosoftExcel.avif new file mode 100644 index 00000000..12471314 Binary files /dev/null and b/public/icons/MicrosoftExcel.avif differ diff --git a/public/icons/MicrosoftForms.png b/public/icons/MicrosoftForms.png new file mode 100644 index 00000000..471623a8 Binary files /dev/null and b/public/icons/MicrosoftForms.png differ diff --git a/public/icons/MicrosoftMailAndCalendar.png b/public/icons/MicrosoftMailAndCalendar.png new file mode 100644 index 00000000..3e170860 Binary files /dev/null and b/public/icons/MicrosoftMailAndCalendar.png differ diff --git a/public/icons/MicrosoftMaps.png b/public/icons/MicrosoftMaps.png new file mode 100644 index 00000000..ad0400f3 Binary files /dev/null and b/public/icons/MicrosoftMaps.png differ diff --git a/public/icons/MicrosoftMoney.png b/public/icons/MicrosoftMoney.png new file mode 100644 index 00000000..6bd2954f Binary files /dev/null and b/public/icons/MicrosoftMoney.png differ diff --git a/public/icons/MicrosoftMoviesTV.png b/public/icons/MicrosoftMoviesTV.png new file mode 100644 index 00000000..c48761c9 Binary files /dev/null and b/public/icons/MicrosoftMoviesTV.png differ diff --git a/public/icons/MicrosoftNews.png b/public/icons/MicrosoftNews.png new file mode 100644 index 00000000..c20171d8 Binary files /dev/null and b/public/icons/MicrosoftNews.png differ diff --git a/public/icons/MicrosoftNotepad.png b/public/icons/MicrosoftNotepad.png new file mode 100644 index 00000000..010d71f3 Binary files /dev/null and b/public/icons/MicrosoftNotepad.png differ diff --git a/public/icons/MicrosoftOneDrive.avif b/public/icons/MicrosoftOneDrive.avif new file mode 100644 index 00000000..11296d7f Binary files /dev/null and b/public/icons/MicrosoftOneDrive.avif differ diff --git a/public/icons/MicrosoftOneNote.png b/public/icons/MicrosoftOneNote.png new file mode 100644 index 00000000..738b36fe Binary files /dev/null and b/public/icons/MicrosoftOneNote.png differ diff --git a/public/icons/MicrosoftOutlook.png b/public/icons/MicrosoftOutlook.png new file mode 100644 index 00000000..3b23c63f Binary files /dev/null and b/public/icons/MicrosoftOutlook.png differ diff --git a/public/icons/MicrosoftPaint.png b/public/icons/MicrosoftPaint.png new file mode 100644 index 00000000..d90bbc47 Binary files /dev/null and b/public/icons/MicrosoftPaint.png differ diff --git a/public/icons/MicrosoftPaint3D.png b/public/icons/MicrosoftPaint3D.png new file mode 100644 index 00000000..209a6739 Binary files /dev/null and b/public/icons/MicrosoftPaint3D.png differ diff --git a/public/icons/MicrosoftPhoneLink.png b/public/icons/MicrosoftPhoneLink.png new file mode 100644 index 00000000..60b9a478 Binary files /dev/null and b/public/icons/MicrosoftPhoneLink.png differ diff --git a/public/icons/MicrosoftPhoto.png b/public/icons/MicrosoftPhoto.png new file mode 100644 index 00000000..6aa2d5e7 Binary files /dev/null and b/public/icons/MicrosoftPhoto.png differ diff --git a/public/icons/MicrosoftPowerBI.png b/public/icons/MicrosoftPowerBI.png new file mode 100644 index 00000000..184f8412 Binary files /dev/null and b/public/icons/MicrosoftPowerBI.png differ diff --git a/public/icons/MicrosoftPowerToys.png b/public/icons/MicrosoftPowerToys.png new file mode 100644 index 00000000..b8ce839a Binary files /dev/null and b/public/icons/MicrosoftPowerToys.png differ diff --git a/public/icons/MicrosoftPowerpoint.png b/public/icons/MicrosoftPowerpoint.png new file mode 100644 index 00000000..23745bf0 Binary files /dev/null and b/public/icons/MicrosoftPowerpoint.png differ diff --git a/public/icons/MicrosoftProject.png b/public/icons/MicrosoftProject.png new file mode 100644 index 00000000..ce58184c Binary files /dev/null and b/public/icons/MicrosoftProject.png differ diff --git a/public/icons/MicrosoftPublisher.avif b/public/icons/MicrosoftPublisher.avif new file mode 100644 index 00000000..69eb45c2 Binary files /dev/null and b/public/icons/MicrosoftPublisher.avif differ diff --git a/public/icons/MicrosoftRemoteDesktop.png b/public/icons/MicrosoftRemoteDesktop.png new file mode 100644 index 00000000..f020ea6e Binary files /dev/null and b/public/icons/MicrosoftRemoteDesktop.png differ diff --git a/public/icons/MicrosoftSCCM.webp b/public/icons/MicrosoftSCCM.webp new file mode 100644 index 00000000..06fa90fd Binary files /dev/null and b/public/icons/MicrosoftSCCM.webp differ diff --git a/public/icons/MicrosoftSnippingTool.png b/public/icons/MicrosoftSnippingTool.png new file mode 100644 index 00000000..56677f7f Binary files /dev/null and b/public/icons/MicrosoftSnippingTool.png differ diff --git a/public/icons/MicrosoftSoundRecorder.png b/public/icons/MicrosoftSoundRecorder.png new file mode 100644 index 00000000..9fc2cb69 Binary files /dev/null and b/public/icons/MicrosoftSoundRecorder.png differ diff --git a/public/icons/MicrosoftStickyNotes.png b/public/icons/MicrosoftStickyNotes.png new file mode 100644 index 00000000..1bb0c307 Binary files /dev/null and b/public/icons/MicrosoftStickyNotes.png differ diff --git a/public/icons/MicrosoftStore.png b/public/icons/MicrosoftStore.png new file mode 100644 index 00000000..c19f3e61 Binary files /dev/null and b/public/icons/MicrosoftStore.png differ diff --git a/public/icons/MicrosoftSystMon.png b/public/icons/MicrosoftSystMon.png new file mode 100644 index 00000000..7b38afee Binary files /dev/null and b/public/icons/MicrosoftSystMon.png differ diff --git a/public/icons/MicrosoftTeams.png b/public/icons/MicrosoftTeams.png new file mode 100644 index 00000000..4633e9b2 Binary files /dev/null and b/public/icons/MicrosoftTeams.png differ diff --git a/public/icons/MicrosoftTips.png b/public/icons/MicrosoftTips.png new file mode 100644 index 00000000..9beb3166 Binary files /dev/null and b/public/icons/MicrosoftTips.png differ diff --git a/public/icons/MicrosoftTodo.png b/public/icons/MicrosoftTodo.png new file mode 100644 index 00000000..f0fd2471 Binary files /dev/null and b/public/icons/MicrosoftTodo.png differ diff --git a/public/icons/MicrosoftVisio.png b/public/icons/MicrosoftVisio.png new file mode 100644 index 00000000..28d1f93f Binary files /dev/null and b/public/icons/MicrosoftVisio.png differ diff --git a/public/icons/MicrosoftWeather.png b/public/icons/MicrosoftWeather.png new file mode 100644 index 00000000..4c04339b Binary files /dev/null and b/public/icons/MicrosoftWeather.png differ diff --git a/public/icons/MicrosoftWhiteboard.png b/public/icons/MicrosoftWhiteboard.png new file mode 100644 index 00000000..10e29640 Binary files /dev/null and b/public/icons/MicrosoftWhiteboard.png differ diff --git a/public/icons/MicrosoftWord.webp b/public/icons/MicrosoftWord.webp new file mode 100644 index 00000000..ca14787d Binary files /dev/null and b/public/icons/MicrosoftWord.webp differ diff --git a/public/icons/MicrosoftWordpad.webp b/public/icons/MicrosoftWordpad.webp new file mode 100644 index 00000000..5291dcf1 Binary files /dev/null and b/public/icons/MicrosoftWordpad.webp differ diff --git a/public/icons/NETRuntime.svg b/public/icons/NETRuntime.svg new file mode 100644 index 00000000..44bb498b --- /dev/null +++ b/public/icons/NETRuntime.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/public/icons/VisualStudio.svg b/public/icons/VisualStudio.svg new file mode 100644 index 00000000..973cc689 --- /dev/null +++ b/public/icons/VisualStudio.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/icons/VisualStudioCode.svg b/public/icons/VisualStudioCode.svg new file mode 100644 index 00000000..c453e633 --- /dev/null +++ b/public/icons/VisualStudioCode.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/icons/WhatsApp.svg b/public/icons/WhatsApp.svg new file mode 100644 index 00000000..c79479fe --- /dev/null +++ b/public/icons/WhatsApp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/application-icon-black.svg b/public/icons/application-icon-black.svg new file mode 100644 index 00000000..58feb6ec --- /dev/null +++ b/public/icons/application-icon-black.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/public/icons/application-icon-white.svg b/public/icons/application-icon-white.svg new file mode 100644 index 00000000..4bb9cf18 --- /dev/null +++ b/public/icons/application-icon-white.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/public/icons/bazel.svg b/public/icons/bazel.svg new file mode 100644 index 00000000..d2577186 --- /dev/null +++ b/public/icons/bazel.svg @@ -0,0 +1,2 @@ + +file_type_bazel \ No newline at end of file diff --git a/public/icons/bravebrowser.svg b/public/icons/bravebrowser.svg new file mode 100644 index 00000000..9aa47f3c --- /dev/null +++ b/public/icons/bravebrowser.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/cmake.svg b/public/icons/cmake.svg new file mode 100644 index 00000000..28e4aeac --- /dev/null +++ b/public/icons/cmake.svg @@ -0,0 +1,3 @@ + + +image/svg+xml \ No newline at end of file diff --git a/public/icons/firefox.svg b/public/icons/firefox.svg new file mode 100644 index 00000000..b5ab67e0 --- /dev/null +++ b/public/icons/firefox.svg @@ -0,0 +1,120 @@ + + + + Firefox Browser logo + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Firefox Browser logo + + + + \ No newline at end of file diff --git a/public/icons/gaming-icon-black.svg b/public/icons/gaming-icon-black.svg new file mode 100644 index 00000000..33d75b1d --- /dev/null +++ b/public/icons/gaming-icon-black.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/public/icons/gaming-icon-white.svg b/public/icons/gaming-icon-white.svg new file mode 100644 index 00000000..029d8528 --- /dev/null +++ b/public/icons/gaming-icon-white.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/public/icons/imagemagick.svg b/public/icons/imagemagick.svg new file mode 100644 index 00000000..a576b78d --- /dev/null +++ b/public/icons/imagemagick.svg @@ -0,0 +1,2919 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/icons/llvm.svg b/public/icons/llvm.svg new file mode 100644 index 00000000..0fa89ec2 --- /dev/null +++ b/public/icons/llvm.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/public/icons/microsoftintune.svg b/public/icons/microsoftintune.svg new file mode 100644 index 00000000..5e83e783 --- /dev/null +++ b/public/icons/microsoftintune.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/node.svg b/public/icons/node.svg new file mode 100644 index 00000000..0dbc49a3 --- /dev/null +++ b/public/icons/node.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/notepadpp.webp b/public/icons/notepadpp.webp new file mode 100644 index 00000000..3c9c59f6 Binary files /dev/null and b/public/icons/notepadpp.webp differ diff --git a/public/icons/openblas.svg b/public/icons/openblas.svg new file mode 100644 index 00000000..96f419bd --- /dev/null +++ b/public/icons/openblas.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/public/icons/python.svg b/public/icons/python.svg new file mode 100644 index 00000000..3a4e6547 --- /dev/null +++ b/public/icons/python.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/icons/qt.svg b/public/icons/qt.svg new file mode 100644 index 00000000..97d0f41f --- /dev/null +++ b/public/icons/qt.svg @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/public/icons/spotify.svg b/public/icons/spotify.svg new file mode 100644 index 00000000..fc3a68bd --- /dev/null +++ b/public/icons/spotify.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/sse2neon.png b/public/icons/sse2neon.png new file mode 100644 index 00000000..37a27298 Binary files /dev/null and b/public/icons/sse2neon.png differ diff --git a/public/icons/tcltk.svg b/public/icons/tcltk.svg new file mode 100644 index 00000000..ac6ac3cb --- /dev/null +++ b/public/icons/tcltk.svg @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/icons/vlc.svg b/public/icons/vlc.svg new file mode 100644 index 00000000..fa23fe06 --- /dev/null +++ b/public/icons/vlc.svg @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/icons/wix.svg b/public/icons/wix.svg new file mode 100644 index 00000000..6e6cb234 --- /dev/null +++ b/public/icons/wix.svg @@ -0,0 +1,20 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/mstile-144x144.png b/public/mstile-144x144.png new file mode 100644 index 00000000..1768ea04 Binary files /dev/null and b/public/mstile-144x144.png differ diff --git a/public/mstile-150x150.png b/public/mstile-150x150.png new file mode 100644 index 00000000..48182d38 Binary files /dev/null and b/public/mstile-150x150.png differ diff --git a/public/mstile-310x150.png b/public/mstile-310x150.png new file mode 100644 index 00000000..139674e5 Binary files /dev/null and b/public/mstile-310x150.png differ diff --git a/public/mstile-310x310.png b/public/mstile-310x310.png new file mode 100644 index 00000000..4b2ca68b Binary files /dev/null and b/public/mstile-310x310.png differ diff --git a/public/mstile-70x70.png b/public/mstile-70x70.png new file mode 100644 index 00000000..e84a1113 Binary files /dev/null and b/public/mstile-70x70.png differ diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 00000000..aeec1e55 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +Sitemap: https://www.worksonwoa.com/sitemap-index.xml \ No newline at end of file diff --git a/public/safari-pinned-tab.svg b/public/safari-pinned-tab.svg new file mode 100644 index 00000000..6dc40a8a --- /dev/null +++ b/public/safari-pinned-tab.svg @@ -0,0 +1,31 @@ + + + + +Created by potrace 1.14, written by Peter Selinger 2001-2017 + + + + + diff --git a/public/site.webmanifest b/public/site.webmanifest new file mode 100644 index 00000000..b20abb7c --- /dev/null +++ b/public/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/src/assets/Linaro-Logo.svg b/src/assets/Linaro-Logo.svg new file mode 100644 index 00000000..4b82cdf7 --- /dev/null +++ b/src/assets/Linaro-Logo.svg @@ -0,0 +1 @@ +Linaro-Logo \ No newline at end of file diff --git a/src/assets/Linaro-White.svg b/src/assets/Linaro-White.svg new file mode 100644 index 00000000..8725c49c --- /dev/null +++ b/src/assets/Linaro-White.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/WoA-banner.png b/src/assets/WoA-banner.png new file mode 100644 index 00000000..32ed1393 Binary files /dev/null and b/src/assets/WoA-banner.png differ diff --git a/src/assets/powered-by-linaro.svg b/src/assets/powered-by-linaro.svg new file mode 100644 index 00000000..f011c6b0 --- /dev/null +++ b/src/assets/powered-by-linaro.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/auth_routes/api/[...auth].js b/src/auth_routes/api/[...auth].js new file mode 100644 index 00000000..3706f300 --- /dev/null +++ b/src/auth_routes/api/[...auth].js @@ -0,0 +1,69 @@ +export const prerender = false +import { Auth } from '@auth/core' +import authConfig from "../../../auth.config.ts" +import { parseString } from 'set-cookie-parser' + +const actions = [ + 'providers', + 'session', + 'csrf', + 'signin', + 'signout', + 'callback', + 'verify-request', + 'error', +] + +function AstroAuthHandler(prefix, options) { + return async ({ cookies, request, redirect }) => { + const url = new URL(request.url) + const action = url.pathname.slice(prefix.length + 1).split('/')[0] + + if (!actions.includes(action) || !url.pathname.startsWith(prefix + '/')) return + + const res = await Auth(request, options) + if (['callback', 'signin', 'signout'].includes(action)) { + // Properly handle multiple Set-Cookie headers (they can't be concatenated in one) + res.headers.getSetCookie().forEach((cookie) => { + const { name, value, ...options } = parseString(cookie) + // Astro's typings are more explicit than @types/set-cookie-parser for sameSite + cookies.set(name, value, options) + }) + try { + res.headers.delete('Set-Cookie') + } catch (error) { + const mutableHeaders = new Headers(res.headers) + console.log(res) + mutableHeaders.delete('Set-Cookie') + return new Response(res.body, { + status: res.status, + headers: mutableHeaders + }) + } + } + return res + } +} + +export function AstroAuth(options) { + // @ts-ignore + const { AUTH_SECRET, AUTH_TRUST_HOST, VERCEL, NODE_ENV } = import.meta.env + + options.secret ??= AUTH_SECRET + options.trustHost ??= !!(AUTH_TRUST_HOST ?? VERCEL ?? NODE_ENV !== 'production') + + const { prefix = '/api/auth', ...authOptions } = options + + const handler = AstroAuthHandler(prefix, authOptions) + return { + async GET(context) { + return await handler(context) + }, + async POST(context) { + return await handler(context) + }, + } +} + + +export const { GET, POST } = AstroAuth(authConfig) \ No newline at end of file diff --git a/src/auth_routes/auth/access-denied.astro b/src/auth_routes/auth/access-denied.astro new file mode 100644 index 00000000..f287e801 --- /dev/null +++ b/src/auth_routes/auth/access-denied.astro @@ -0,0 +1,37 @@ +--- +import { getSession } from "auth-astro/server"; + +Astro.response.headers.delete('Set-Cookie'); +const session = await getSession(Astro.request) as any; +console.log(session) +--- + + + + + +

+ You do not have permission to see this site. Please contact{" "} + Linaro IT Support to be granted + permission. +

+