Skip to content

Commit 90181e8

Browse files
committed
sync
1 parent b0b28bf commit 90181e8

32 files changed

+533
-30
lines changed

cli/docker/Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node:19 as node_builder
1+
FROM node:19 AS node_builder
22

33
WORKDIR /app
44
ENV NODE_ENV=development
@@ -10,7 +10,7 @@ RUN npm install && \
1010

1111
#########################################
1212

13-
FROM maven:3-openjdk-8 as java_builder
13+
FROM maven:3-openjdk-8 AS java_builder
1414

1515
RUN mkdir -p /app && \
1616
cd /app && \
@@ -22,7 +22,7 @@ WORKDIR /app
2222
#########################################
2323

2424
FROM ruby:3.2.2-alpine
25-
MAINTAINER "Christoph Fabianek" christoph@ownyourdata.eu
25+
LABEL org.opencontainers.image.authors="Christoph Fabianek <christoph@ownyourdata.eu>"
2626

2727
RUN addgroup -S user && \
2828
adduser -S user -G user && \

repo2/Gemfile.extend

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
# Storage Provder
1+
# turtle output
2+
gem 'rdf'
3+
gem 'rdf-normalize'
4+
gem 'rdf-turtle'
5+
gem 'json-ld'
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
module Api
2+
module V1
3+
class ResourcesController < ApiController
4+
5+
include UsersHelper
6+
7+
# possible values vor ENV["AUTH"]
8+
# - empty, "false" => no authorization necessary
9+
# - "optional" => optional authorization
10+
# - "true" => require key&secret
11+
# - "idaustria" => show "Login with ID Austria" button and anyone with ID Austria can login
12+
# - "idaustria_restrict" => show "Login with ID Austria" button and bPK is mapped to OAuth Apps
13+
def active
14+
env_auth = ENV["AUTH"].to_s.downcase
15+
if ENV["AUTH_SCOPE"].nil?
16+
retVal = { "active": true,
17+
"auth": !(env_auth == "" || env_auth == "false") ,
18+
"repos": false
19+
}
20+
else
21+
retVal = { "active": true,
22+
"auth": !(env_auth == "" || env_auth == "false") ,
23+
"repos": false,
24+
"scopes": JSON.parse(ENV["AUTH_SCOPE"].to_s)
25+
}
26+
end
27+
if env_auth == "optional"
28+
retVal["auth"] = false
29+
retVal["auth_method"] = {mode: "optional"}
30+
end
31+
if !doorkeeper_name.nil?
32+
retVal["user"] = {user_name: doorkeeper_name, full_name: "Administrator", organization: "OwnYourData"}
33+
end
34+
if env_auth.start_with?("idaustria")
35+
uid = SecureRandom.uuid
36+
IdaustriaUuid.where('created_at < ?', 2.hours.ago).destroy_all
37+
@ida = IdaustriaUuid.new(uuid: uid)
38+
ida_short = env_auth.split(':').last rescue ""
39+
if @ida.save && ida_short != ""
40+
eid_url = 'https://eid.oesterreich.gv.at/auth/idp/profile/oidc/authorize'
41+
eid_url += '?response_type=code'
42+
eid_url += '&client_id=https%3A%2F%2Fidaustria.ownyourdata.eu'
43+
eid_url += '&redirect_uri=https%3A%2F%2Fidaustria.ownyourdata.eu%2Fconnect'
44+
eid_url += '&scope=openid+profile+eid'
45+
eid_url += '&state=' + ida_short + ':' + uid
46+
retVal["oauth"] = [{
47+
link: eid_url,
48+
title: {
49+
en: "Login with ID Austria",
50+
de: "mit ID Austria einloggen",
51+
pic: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="
52+
}
53+
}]
54+
end
55+
end
56+
57+
render json: retVal,
58+
status: 200
59+
end
60+
61+
def info
62+
container_name = ENV["CONTAINER_NAME"] || "Container Name"
63+
container_description = ENV["CONTAINER_DESCRIPTION"] || "here is the description and purpose of the container"
64+
retVal = {
65+
"name": container_name.to_s,
66+
"description": container_description.to_s
67+
}
68+
render json: retVal,
69+
status: 200
70+
end
71+
72+
def idaustria
73+
74+
STDOUT.sync = true
75+
logger = Logger.new(STDOUT)
76+
level ||= LOGLEVELS.index ENV.fetch("LOG_LEVEL","INFO")
77+
level ||= Logger::INFO
78+
logger.level = level
79+
80+
# decode token ---------------------
81+
token = params[:token] rescue nil
82+
data = JWT.decode(token, nil, false).first rescue nil
83+
if data.nil?
84+
logger.error("invalid token '" + token.to_s + "'")
85+
redirect_to '/'
86+
return
87+
end
88+
89+
# check state ----------------------
90+
state = data['state'].split(':').last
91+
@idu = IdaustriaUuid.find_by_uuid(state) rescue nil
92+
if @idu.nil?
93+
logger.error("invalid state '" + state.to_s + "'")
94+
redirect_to '/'
95+
return
96+
end
97+
@idu.delete
98+
99+
# check signature ------------------
100+
sig = data.delete("sig") rescue ""
101+
my_hash = Oydid.hash(Oydid.canonical(data)) rescue ""
102+
publicKey = Oydid.read(ENV['IDAUSTRIA_DID'], {}).first["doc"]["key"].split(':').first rescue ""
103+
check, msg = Oydid.verify(my_hash, sig, publicKey)
104+
if !check
105+
logger.error("invalid signature '" + sig.to_s + "'")
106+
redirect_to '/'
107+
return
108+
end
109+
110+
# check expired token --------------
111+
exp = data["exp"].to_i
112+
if exp < Time.now.to_i
113+
logger.error("expired token '" + exp.to_s + "'")
114+
redirect_to '/'
115+
return
116+
end
117+
118+
# check valid bpk ------------------
119+
bpk = data["urn:pvpgvat:oidc.bpk"].to_s
120+
if bpk == ""
121+
logger.error("empty bpk")
122+
redirect_to '/'
123+
return
124+
end
125+
126+
# document login with ID Austria ---
127+
logger.info("ID Austria Login from: " + data["given_name"].to_s + " " + data["family_name"].to_s + " (" + bpk + ")")
128+
129+
env_auth = ENV["AUTH"].to_s.downcase.split(':').first
130+
ida_scope = ENV["IDAUSTRIA_SCOPE"] || "read"
131+
case env_auth
132+
when "idaustria"
133+
# variant #1: temporary credentials
134+
@da = Doorkeeper::Application.find_by_bpk(bpk)
135+
if @da.nil?
136+
@da = Doorkeeper::Application.new(
137+
name: "ida_login_" + SecureRandom.uuid,
138+
redirect_uri: "urn:ietf:wg:oauth:2.0:oob",
139+
scopes: ida_scope,
140+
bpk: bpk,
141+
temp: true)
142+
if !@da.save
143+
redirect_to '/'
144+
end
145+
end
146+
Doorkeeper::Application.where(temp: true).where('updated_at < ?', 2.hours.ago).destroy_all
147+
else
148+
# variant #2: selected Oauth
149+
@da = Doorkeeper::Application.find_by_bpk(bpk)
150+
if @da.nil?
151+
logger.error("invalid bpk '" + bpk + "'")
152+
redirect_to '/'
153+
return
154+
end
155+
end
156+
157+
redirect_to '/?APP_KEY=' + @da.uid.to_s + "&APP_SECRET=" + @da.secret
158+
end
159+
160+
end
161+
end
162+
163+
# template for multiple versions -> copy into folder controllers/api/v2
164+
# module V2
165+
# class ResourcesController < ApiController
166+
# def active2
167+
# render json: [2],
168+
# status: 200
169+
# end
170+
# end
171+
# end
172+
end

repo2/app/controllers/api/v1/soya_controller.rb

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,21 @@ def read
1414
render json: {"error": "not found"},
1515
status: 404
1616
else
17-
retval = {
18-
content: @store.item,
19-
"id": @store.id,
20-
"dri": @store.soya_dri,
21-
"soya_name": @store.soya_name,
22-
}
17+
if @store.soya_tag == "current"
18+
retval = {
19+
content: @store.item,
20+
"id": @store.id,
21+
"dri": @store.soya_name,
22+
"soya_name": @store.soya_name,
23+
}
24+
else
25+
retval = {
26+
content: @store.item,
27+
"id": @store.id,
28+
"dri": @store.soya_dri,
29+
"soya_name": @store.soya_name,
30+
}
31+
end
2332
render json: retval.to_json,
2433
status: 200
2534
end
@@ -49,7 +58,19 @@ def query
4958
end
5059
end
5160
end
52-
render json: retVal,
61+
62+
sortedRetVal = retVal.sort_by do |i|
63+
name = i[:name]
64+
65+
# Check if the name starts with "zQm" (case-sensitive)
66+
if name.start_with?("zQm")
67+
[1, name] # Group for "zQm", sort alphabetically within this group
68+
else
69+
[0, name.downcase] # Group for all other names, case-insensitive alphabetical sorting
70+
end
71+
end
72+
73+
render json: sortedRetVal,
5374
status: 200
5475
end
5576

@@ -82,7 +103,17 @@ def info
82103
end
83104
end
84105
end
85-
render json: retVal,
106+
sortedRetVal = retVal.sort_by do |i|
107+
name = i[:name]
108+
109+
# Check if the name starts with "zQm" (case-sensitive)
110+
if name.start_with?("zQm")
111+
[1, name] # Group for "zQm", sort alphabetically within this group
112+
else
113+
[0, name.downcase] # Group for all other names, case-insensitive alphabetical sorting
114+
end
115+
end
116+
render json: sortedRetVal,
86117
status: 200
87118
end
88119

repo2/app/controllers/dri_controller.rb

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,26 @@ def read
2424
status: 200
2525
end
2626

27+
def read_ttl
28+
store_id, msg = get_soya(params[:dri])
29+
if store_id.nil?
30+
render json: {"error": "not found"},
31+
status: 404
32+
return
33+
end
34+
@store = Store.find(store_id) rescue nil
35+
if @store.nil?
36+
render json: {"error": "not found"},
37+
status: 404
38+
return
39+
end
40+
41+
jsonld = @store.item
42+
graph = RDF::Graph.new << JSON::LD::Reader.new(@store.item.to_json)
43+
render plain: graph.dump(:turtle, standard_prefixes: true),
44+
status: 200
45+
end
46+
2747
def read_yaml
2848
store_id, msg = get_soya(params[:dri])
2949
if store_id.nil?
@@ -116,8 +136,17 @@ def info
116136
date: r.updated_at,
117137
yaml: r.yaml == 'true'
118138
}
139+
end rescue []
140+
sorted_history = history.sort_by do |i|
141+
name = i[:schema]
142+
143+
# Check if the name starts with "zQm" (case-sensitive)
144+
if name.start_with?("zQm")
145+
[1, name] # Group for "zQm", sort alphabetically within this group
146+
else
147+
[0, name.downcase] # Group for all other names, case-insensitive alphabetical sorting
119148
end
120-
.sort_by{ |i| i["date"] } rescue []
149+
end
121150

122151
bases = []
123152
overlays = []
@@ -150,7 +179,7 @@ def info
150179
end
151180
end unless graph == []
152181
end
153-
render json: {"name": soya_name, "dri": soya_dri, "history": history, "bases": bases.uniq, "overlays": overlays.uniq},
182+
render json: {"name": soya_name, "dri": soya_dri, "history": sorted_history, "bases": bases.uniq, "overlays": overlays.uniq},
154183
status: 200
155184

156185
end

repo2/app/helpers/hooks_helper.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
module HooksHelper
22
def write_hook(data)
3+
puts "write_hook:"
4+
puts data.to_json
35
data["processed"] = 1
46
data["responses"] = [{id: data[:id], status: 200}]
57

68
end
79

810
def read_hook(data)
11+
puts "read_hook:"
912
puts data.to_json
1013
@rh_store = Store.find(data["id"]) rescue nil
1114
if !@rh_store.nil?

repo2/app/helpers/soya_helper.rb

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ def get_soya(input)
1111
found = false
1212
@gs_store = Store.find_by_soya_dri(input)
1313
if @gs_store.nil?
14-
soya_name,c,soya_tag = input.rpartition(':')
14+
if input.include?(':')
15+
soya_name,c,soya_tag = input.rpartition(':')
16+
else
17+
soya_name = input
18+
soya_tag = "current"
19+
end
1520
if soya_name != '' && soya_tag != ''
1621
@gs_store = Store.where(soya_name: soya_name, soya_tag: soya_tag)
1722
if !@gs_store.nil? && @gs_store.length > 0
@@ -70,4 +75,15 @@ def similarity(vec1, vec2)
7075
return simvec.inject(:+).to_f / simvec.length # average of simvec
7176
end
7277

78+
def deep_transform_keys_to_strings(value)
79+
case value
80+
when Hash
81+
value.transform_keys(&:to_s).transform_values { |v| deep_transform_keys_to_strings(v) }
82+
when Array
83+
value.map { |v| deep_transform_keys_to_strings(v) }
84+
else
85+
value
86+
end
87+
end
88+
7389
end

0 commit comments

Comments
 (0)